2010-12-15 131 views
1

我有一类的容器(含指针)作为成员:如何返回一个const std :: vector <Object * const>?

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

现在我尝试实施GetVecMyObj()。以下是我想出了...

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

但当然编译器警告我,说我使用分配功能的一个const-对象。有一个更好的方法吗?我的意思是,当然,我不希望VecMyObjs在课堂外改变VecMyObj。如何在没有编译器警告的情况下实现该目标?编辑: 好的。谢谢大家。现在是这样的:

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

但是,我无法绕过分配函数,对吧?例如。如果我想让“一切”保持不变,那么铸造“原创”是行不通的。

+4

你不需要VicMyObjs是GetVecMyObjs函数内部常量......返回时,该资格将被隐式添加。 – 2010-12-15 11:14:42

+0

您确定要使用vector 而不使用vector 吗?为什么通过引用返回const不可行? – Palmik 2010-12-15 11:30:12

+0

关于你的编辑,你希望一切都是恒定的:正如其他人已经指出的,你正在使指针为const,而不是指向的对象。这些可以改变,从而改变你的内部对象。 – stefaanv 2010-12-15 11:54:25

回答

3

我不知道std::vector<MyObject * const>(恒定指针矢量)真的是你想要的东西:我相信你的意思是std::vector<MyObject const *>(指向常量对象的向量)。

  1. 常量性(指针常量性)的“第一级”自然是通过返回对向量恒定的参考来实现。只有const_iterator可以从一个const向量中获得,所以你可以保证指针不会被修改(但pointees可以)。

  2. 常量的“第二级”(10 pointee常量)很难获得。要么返回向量的一个新的实例作为已经指出别人:

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

    或者,如果适用,试图寻找到Boost Pointer Container库(最引人注目的是ptr_vector)它提供,除其他事项外,正确的常量性传播:

    传播常量性,使得一个 不能通过 常量性修改的对象。

您要明白,返回上一个矢量保证它不能被修改const引用(无插入,缺失,或它的值的修改)。所以,在大多数情况下,返回一个const std::vector<T> &是要走的路,因为如果不涉及任何复制。这里的问题实际上是指向容器的特定对象,其中值的常量不提供pointees的常量。

+0

谢谢,我知道有这样的事情......也许我应该开始另一个问题线程,但是“std :: vector 和“const vector then?还是一样? – AudioDroid 2010-12-15 12:12:05

+1

@AudioDroid:no:你可以修改一个非常量向量('push_back','erase',...),而你不能修改一个const向量(从某种意义上说,它只提供只读访问到已经存储的元素)。但是,关于元素*的常量*,它们提供了相同的保证。 – icecrime 2010-12-15 12:18:09

+0

太好了。谢谢!如果你可以仔细检查我自己的答案....我希望我完全理解你。 – AudioDroid 2010-12-15 12:33:52

2

如果你想返回一个新的vector,不要使它const。将const关键字放在*之前。

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

我省略了转换TRoadSgmt因为你没有指定这个类的继承。

+0

糟糕,[TRoadSgmt]并不打算在这个一般的例子中。我只是纠正它。 – AudioDroid 2010-12-15 11:34:26

0

除了将签名删除从vectorconst(因为它是载体的拷贝),我假设你不想外面的人来修改的内容,因此,做一个const指针,即

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

现在返回向量的副本,其中包含常量指针(这意味着你不能修改通过该指针所指向的对象) - 阱是这样的协议,没有什么阻止他人const_cast是荷兰国际集团这就是(反正使用UB!)

如果您确实想要阻止修改,请返回向量中的副本(或每个对象的克隆)。

+0

“VecMyObjs”声明中的'const'关键字出错。 – 2010-12-15 11:24:56

+0

我虽然语法“常量矢量,可确保‘向量的内容’(在这种情况下:所有的指针MyObjects)!不断 – AudioDroid 2010-12-15 11:29:42

+0

@larsmans - 教我要盲目照搬THX,固定@AudioDroid,我不这么认为,它不仅使'VECTOR'对象不变,我不相信有什么它拥有的任何担保.. – Nim 2010-12-15 11:40:33

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

这似乎是对我的解决方案。我现在可以告诉我,得到所有不同的帖子。 谢谢大家!有一个很好的一个... (或者让我知道,如果我还是错的地方。)

+0

你是返回一个新的载体的实例,所以在使返回的矢量常量是没有意义的(这是一个副本,无论如何,为什么你会介意调用者'push_back'的东西呢?) – icecrime 2010-12-15 12:32:03

+1

@icecrime:在一个临时对象上调用一个变异操作很可能是一个错误,返回一个'const'对象会捕获客户端代码凯斯是一个不正确的假设,也许他们正在参考。防止'clz.GetVecMyObjs()。push_back(x)'可能是一件好事。返回一个const对象不会阻止返回值的正常拷贝,例如'vector cpy = clz.GetVecMyObjs(); cpy.push_back(X);'。 – 2010-12-15 12:46:42

+0

@Charles Bailey:你是对的,那是我没有考虑的东西 – icecrime 2010-12-15 12:48:07

1

假设非const指针的向量驻留在整个生命周期中的某个地方,您将使用const版本,因此您不需要副本,并且如果有很多这样的指针,想要复制矢量,最好返回一些自定义的包装对象,只给用户const-access。

向量的第一个元素的地址将是T **,你不能强制转换为const T **(正确),也可以将它转换成const T * const的*(这将是安全的,但该语言不允许它)。

如果你被允许后者将是完美的转换创建只读视图。

相关问题