How-to return a const std::vector<Object *const>?

无人久伴 提交于 2020-01-11 11:51:10

问题


I have a class with a container (containing pointer) as a member:

MyClass{
private:
   std::vector<MyObject*> _VecMyObjs;
public:
   const std::vector<MyObject* const> GetVecMyObj();
}

Now I try to implement GetVecMyObj(). Here is what I came up with...

const vector<MyObject *const> ACI_CALL MyClass::GetVecMyObjs()
{
   const vector<MyObject *const> VecMyObjs;
   VecMyObjs.assign( _VecMyObjs.begin(), _VecMyObjs.end());
   return VecMyObjs;
}

But of course the compiler is warning me, that I use the assign-function on a const-Object. Is there a better way to do this? I mean, I don't want VecMyObjs to change VecMyObj outside of the class, of course. How can I achieve that without a compiler warning?

EDIT: Okay. Thank you everybody. It's now like this:

const vector<MyObject *const> ACI_CALL MyClass::GetVecMyObjs()
{
   const vector<MyObject *const> VecMyObjs;
   VecMyObjs.assign( _VecMyObjs.begin(), _VecMyObjs.end());
   return VecMyObjs;
}

But, I can't get around the assign-function, right? E.g. casting the "original" doesn't work, if I want "everything" to be constant.


回答1:


I'm not sure std::vector<MyObject * const> (vector of constant pointers) is really what you want : I believe you mean std::vector<MyObject const *> (vector of pointer to constant objects).

  1. The "first level" of constness (pointer constness) is naturally achieved by returning a constant reference on the vector. Only const_iterator can be obtained from a const vector, so you have a guarantee that the pointers won't be modified (but pointees can be).

  2. The "second level" of constness (pointee constness) is harder to obtain. Either return a new instance of a vector as already pointed out by others :

    return std::vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end());
    

    Or, if applicable, try to look into the Boost Pointer Container library (and most notably ptr_vector) which offers, among other things, correct constness propagation :

    Propagates constness such that one cannot modify the objects via a const_iterator.

You have to understand that returning a const reference on a vector guarantees that it cannot be modified (no insertion, deletion, or modification of its value). So, in most cases, returning a const std::vector<T> & is the way to go because if does not involve any copying. The issue here is really specific to container of pointers, where constness of the values does not provide constness of the pointees.




回答2:


If you want to return a fresh vector, don't make it const. Put the const keyword before the *.

std::vector<MyObject const*> MyClass::GetVecMyObj()
{
    return std::vector<MyObject const*>(_VecMyObjs.begin(), _VecMyObjs.end());
}

I omitted the conversion to TRoadSgmt as you didn't specify the inheritance of this class.




回答3:


Assuming the vector of the non-const pointers resides somewhere during the entire lifetime that you are going to use the const-version so you don't need a copy, and if there a lot of them so you don't want to copy the vector, you are better off returning some kind of wrapper object that is custom made to only give the user const-access.

The address of the first element of the vector will be T** and you can't cast that to const T** (correctly) nor can you cast it to const T*const * (which would be safe but the language does not allow it).

If you were allowed to convert the latter it would be perfect for creating a read-only view.




回答4:


Aside from changing the signature to remove the const from the vector (as it's a copy of the vector), I'm assuming that you don't want people outside to modify the contents, as a result, make a const pointer , i.e.

vector<const MyObject *> ACI_CALL MyClass::GetVecMyObjs()
{
   return vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end());
}

Now the returned vector is a copy, which contain const pointer (which means you can't modify the pointed object via this pointer) - well that's the agreement, there's nothing preventing someone from const_casting that away (using that is UB anyways!)

If you really want to prevent modifications, return a copy (or clone of each object) in the vector.




回答5:


const vector<const MyObject *> MyClass::GetVecMyObjs() const
{
   return vector<const MyObject *>(_VecMyObjs.begin(), _VecMyObjs.end());
}

This seems to be the solution to me. I can tell now, thanks to all the different posts I got. Thanks all of you! Have a nice one... (Or let me know, if I am still wrong somewhere.)



来源:https://stackoverflow.com/questions/4449227/how-to-return-a-const-stdvectorobject-const

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!