0

I am trying to erase a vector of pointers that I pass by value into some function. The reason why I pass by value is that I plan to erase these values in numerous calls to the function. So if I pass by pointer/reference I could not achieve this.

First of all is the statement above correct?

Here is some example code:

vector<Boson*>* BosonMaker::remove_duplicates(vector<Boson*>* boson_candidates, vector<Particle*> child_candidates){
  vector<Particle*> used_leptons.clear();

  // This needs deleting at some point
  m_unduplicated_bosons = new vector<Boson*>();

  for(int i_b = 0; boson_candidates->size(); i_b++){

    vector<Particle*>::iterator child1_finder = find(used_leptons.begin(), used_leptons.end(), boson_candidates->at(i_b)->Child1());

    //Search pointer will reach end of collection if child isn't in the used_leptons vector
    if (child1_finder == used_leptons.end()) {
      vector<Particle*>::iterator child2_finder = find(used_leptons.begin(), used_leptons.end(), boson_candidates->at(i_b)->Child2());

      if (child2_finder == used_leptons.end()) {
        used_leptons.push_back(boson_candidates->at(i_b)->Child1());
        used_leptons.push_back(boson_candidates->at(i_b)->Child2());
        // And add the boson to the vector of final bosons
        unduplicated_bosons->push_back(boson_candidates->at(i_b));
      }
    }

  }
  // Now make a vector of unused leptons
  for (int i_l = 0; i_l < used_leptons.size(); i_l++) {
       vector<Particle*>::iterator lepton_finder = find(child_candidates.begin(), child_candidates.end(), used_leptons.at(i_l));
       child_candidates.erase(lepton_finder);  
  }

  return unduplicated_bosons;
}

I would then use this member function inside the class like so

vector<Boson*> *m_boson_finals_elpair = remove_duplicates(&m_boson_electronPair_candidates, m_all_particle_candidates);
vector<Boson*> *m_boson_finals_mupair = remove_duplicates(&m_boson_muonPair_candidates, m_all_particle_candidates);

vector<Boson*> *m_boson_finals_elneutrino = remove_duplicates(&m_boson_electronNeutrino_candidates, m_all_particle_candidates);
vector<Boson*> *m_boson_finals_muneutrino = remove_duplicates(&m_boson_muonNeutrino_candidates, m_all_particle_candidates);

My question is:

Would m_all_particle_candidates which is

vector<Particle*>  m_all_particle_candidates;

be different in each call of remove_duplicates?

I think I am trying to ask is the iterator lepton_finder erased from the vector and not the actual object Particle since I have passed by value?

Note: There was a typo in the remove_duplicate function. I passed by pointer and not value. it should be value

BenMorel
  • 34,448
  • 50
  • 182
  • 322
MWright
  • 1,681
  • 3
  • 19
  • 31
  • I have answered your question here: http://stackoverflow.com/questions/1041620/most-efficient-way-to-erase-duplicates-and-sort-a-c-vector/14844222#14844222 look for the ptgi::unique() article, which describes a replacement for std::unique() that avoids memory leaks, duplicate deletes, and SEGMENTATION FAULTS. -dbednar ahd 310 – joe Feb 13 '13 at 17:36

3 Answers3

1

I'm a little confused about what you are saying about passing by value and passing by reference, so I'm going to give a short explanation on that first:

  • When passing by value, the variable that the method is called with remains unchanged (since a copy is passed into the called method). Be careful though, this case can also incur a heavy performance penalty, since the whole variable is copied! In case of a vector holding many elements this might take quite some time! Passing by value is achieved like this in C++:

  • When passing by reference (or more or less equivalently by pointer) the outer variable is also changed - since you're only passing a reference into the method, which is referencing the same actual space in memory as the original variable!

So basically what the difference is that in when using call by value, the original caller's value remains unchanged, while when using call by reference, a reference to the original caller's value is passed in, and therefore this value can change on both ends.

Now which method is needed simply depends on what you want to achieve. Pass by Value if the variable you're passing into the method should remain unchanged (m_all_particle_candidates in your example). Or if you need it to change, then pass by reference/pointer.

If the passed-in variable shouldn't change, but you also only need a read-only version of the variable inside the method, then the possible performance problems introduced by passing by value can be overcome by using a const reference. In you case, however, you seem to need a full copy (meaning a normal pass-by-value).

codeling
  • 11,056
  • 4
  • 42
  • 71
  • @nyaralthotep Ah yes pass it with a const so this will not change the value of the vector, but the address can still change. could I not just put the whole function as a const. e.x. remove_duplicates(...) const { ... } ? – MWright Jan 05 '12 at 15:22
  • Hm I carefully read your question again and I think I was a little premature in mentioning the const reference; it is of no use in your case (except for the first parameter, maybe). You really need a copy, meaning you need to pass the second parameter by value; I've updated my answer accordingly – codeling Jan 05 '12 at 16:09
  • @nyaralthotep If I pass by const reference how will the vector of pointers be changed (since I use the vector erase method will the const reference be an error )? Hence you are suggesting to pass by value – MWright Jan 05 '12 at 17:19
1

Does the code presented in the OP compile? I don't think so. In fairness, it should be passed through a compiler before posting.

typedef struct {
   long double x, y, z;
} V3;

void fnExpectingPtrToVec(vector<V3> * pvec) {
}

void fnExpectingVec(vector<V3> vec) {
}

void testVecs() {
   vector<V3> v;
   //fnExpectingPtrToVec(v); Does not compile
   fnExpectingPtrToVec(&v);
   fnExpectingVec(v);
}

If it is expecting a pointer to a vector in the 2nd param, and you passed in a vector instead, then its a compile error.

When you fix the function to accept a vector, not a pointer to one, and call it with your vector it will make a copy and the repeated calls to the function will leave m_all_particle_candidates unchanged.

ScrollerBlaster
  • 1,578
  • 2
  • 17
  • 21
0

You're not passing the vector by value.

vector<Boson*>* BosonMaker::remove_duplicates(vector<Boson*>* boson_candidates, vector<Particle*> *child_candidates);

will pass a pointer to the vector by value. But the pointer, which is a copy of the original one, will point to the same vector as the original.

So you're basically changing the same vector as outside the call.

To pass by value, you need:

vector<Boson*>* BosonMaker::remove_duplicates(vector<Boson*> boson_candidates, vector<Particle*> child_candidates);

But be careful when doing so. Copying will occur, so you probably need to override the virtual destructor, copy constructor and assignment operator for Boson and Particle if they're not POD types.

Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625
  • @MWright in that case, edit your question with the new prototype. It should be ok in that case, make sure to override what I said you should. – Luchian Grigore Jan 05 '12 at 15:20