简体   繁体   English

如何返回const std :: vector <Object *const> ?

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

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(). 现在,我尝试实现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. 但是,当然,编译器警告我,我在const-Object上使用了assign-function。 Is there a better way to do this? 有一个更好的方法吗? I mean, I don't want VecMyObjs to change VecMyObj outside of the class, of course. 我的意思是,我当然不希望VecMyObjs在类之外更改VecMyObj。 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? 但是,我无法绕过分配功能,对吗? Eg casting the "original" doesn't work, if I want "everything" to be constant. 例如,如果我希望“一切”保持不变,则强制转换“原始”是无效的。

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). 我不确定std::vector<MyObject * const> (常量指针的向量)是否真的是您想要的:我相信您的意思是std::vector<MyObject const *> (指向常量对象的指针的向量)。

  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). 只有const_iterator可以从一个const矢量来获得,所以你必须保证该指针将不会被修改(但指针对象可以)。

  2. The "second level" of constness ( pointee constness) is harder to obtain. 常数的“第二级”( pointee常数)很难获得。 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 : 或者,如果适用,尝试查看Boost Pointer容器库(最著名的是ptr_vector ),该库除其他外提供正确的constness传播:

    Propagates constness such that one cannot modify the objects via a const_iterator. 传播constness,使人们无法通过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). 您必须了解,在向量上返回const引用可确保无法对其进行修改(不得插入,删除或修改其值)。 So, in most cases, returning a const std::vector<T> & is the way to go because if does not involve any copying. 因此,在大多数情况下,返回const std::vector<T> &是方法,因为if不涉及任何复制。 The issue here is really specific to container of pointers, where constness of the values does not provide constness of the pointees. 这里的问题实际上是特定于指针容器的,其中值的恒定性不提供指针的恒定性。

If you want to return a fresh vector , don't make it const . 如果要返回一个新的vector ,请不要使其为const Put the const keyword before the * . const关键字放在*之前。

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. 我没有转换为TRoadSgmt因为您没有指定此类的继承。

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. 假设非const指针的向量在整个生命周期中都位于某个地方,那么您将使用const-version,因此您不需要复制,如果它们很多,则您不想复制向量,最好返回某种定制的包装对象,只给用户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). 向量的第一个元素的地址将为T **,并且您不能将其强制转换为const T **(正确),也不能将其强制转换为const T * const *(这很安全,但是语言不会允许它)。

If you were allowed to convert the latter it would be perfect for creating a read-only view. 如果允许您转换后者,则非常适合创建只读视图。

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 , ie 除了更改签名以从vector删除const (因为它是vector的副本)之外,我还假设您不希望外界的人修改内容,因此,请创建const指针,即

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_cast ing that away (using that is UB anyways!) 现在返回的向量是一个副本,其中包含const指针(这意味着您无法通过此指针修改指向的对象)-嗯,这就是协议,没有什么阻止有人const_cast放弃这一点(无论如何都使用UB!)

If you really want to prevent modifications, return a copy (or clone of each object) in the vector. 如果您确实想防止修改,请在向量中返回一个副本(或每个对象的副本)。

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.) 有一个好人...(或让我知道,如果我在某个地方还是错的。)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM