tags:

views:

277

answers:

4

I understand that const_cast to remove constness of objects is bad,

I have the following use case,

//note I cannot remove constness in the foo function
foo(const std::vector<Object> & objectVec) {

   ...
   int size = (int) objectVec.size();
   std::vector<Object> tempObjectVec;
   //Indexing here is to just show a part of the vector being
   //modified
   for (int i=0; i < (int) size-5; ++i) {
       Object &a = const_cast<Object&> objectVec[i];
       tempObjectVec.push_back(a);
   } 
   foo1(tempObjectVec);
}

If i change tempObjectVec objects in foo1, will the original objects in ObjectVec change, I say yes since I am passing references, further is this efficient. Can you suggest alternatives.

+3  A: 

Well, that depends on Object. But the Objects are being copied, when you pass them to push_back. You can check this by adding some debug code to the copy constructor. So if Object is well-behaved and keeps distinct copies separate, then foo1 can change the vector it gets all it likes.

A more efficient way to do this would be to have foo1 accept a start and end iterators:

void foo1(std::vector<Object>::const_iterator start,
          std::vector<Object>::const_iterator end);

...
foo1(objectVec.begin(), objectVec.end() - 5);

If you don't use const_cast, then the type system will ensure that foo1 does not change any elements, as these are const_iterators.

luqui
+1  A: 

Your tempObjectVec can't be a vector of references, so I presume it should be declared as something like:

std::vector<Object> tempObjectVec;

When you execute the tempObjectVec.push_back(a), a copy of the object will be made to push it into the tempObjectVec vector. Since this is making a copy, you shouldn't even need to use the const_cast to remove the constness, I'm not clear on why you needed to do that.

Greg Hewgill
edited the code, based on your suggestion.
kal
+1  A: 

I believe this is the statement your looking for:

const_cast<std::vector<Object>&> (objectVec) this will return a reference to a non-const std::vector which should be palatable to foo1 (I'm assuming).

Modifying your original example:

foo(const std::vector<Object> & objectVec) {

    ...
    foo1(const_cast<std::vector<Object> &>(objectVec));
}

However I do recommend looking at the actual requirements of foo1 that require it to use a non-const vector as you seem to be indicating that all your interested in is modifying the Object instances themselves.

Henk
+1  A: 

As other ones already say, your vector's push_back takes the reference, but then it copies the object it references. So, at the end you end up with a copy of objectVec[i] within your tempObjectVec.

A vector can't store references, because they can't be assigned (assignments to it affect not the reference itself, but the object referenced instead), which is a requirement for objects to be held in a vector. References are also no objects. They don't have an own size. They therefor can't be pushed into an array or any vector. Usually you want to store pointers or smart pointers in such a container to reference some other object. Look into the boost pointer container library which looks like exactly what you want.

Johannes Schaub - litb