如何返回向量的“只读”副本
Posted
技术标签:
【中文标题】如何返回向量的“只读”副本【英文标题】:How to return a 'read-only' copy of a vector 【发布时间】:2010-03-17 20:44:37 【问题描述】:我有一个具有私有属性向量 rectVec 的类;
class A
private:
vector<Rect> rectVec;
;
我的问题是如何返回我的 Vector 的“只读”副本? 我正在考虑这样做:
class A
public:
const vect<Rect>& getRectVec() return rectVect;
这是正确的方法吗? 我在想这样可以防止被调用者修改向量(在向量中添加/删除Rect),那么向量里面的Rect呢?
【问题讨论】:
这听起来有点混乱。如果您制作副本,为什么它是否是只读的很重要?如果您想要对原始数据进行只读访问,那么您就不需要制作副本。 【参考方案1】:这是正确的方法,尽管您可能还想创建函数 const
。
class A
public:
const vect<Rect>& getRectVec() const return rectVect;
;
这样人们就可以使用const A
对象调用getRectVec
。
【讨论】:
这似乎不适用于const vector<unique_ptr<T>>&
。有没有办法返回一个只读的向量/STL容器,它的T*
或unique_ptr<T>
对象不能被修改,向量也不能被修改,即。 e.一个完全只读的向量?当然,项目和向量本身应该在持有类中是可更改的。【参考方案2】:
这是正常的方式。 const
表示“你不能修改它”。它也适用于容器内的元素。
一个简单的测试:
#include <vector>
typedef std::vector<int> int_vec;
struct foo
const int_vec& get(void)
return v;
int_vec v;
;
int main(void)
foo f;
f.v.push_back(1);
f.v.push_back(2);
f.v.push_back(3);
f.get()[0] = 2; // nope
const_cast
可用于剥离 const
,但如果您通过它修改变量,则最终会出现未定义的行为:
int_vec& v = const_cast<int_vec&>(f.get()); // this is okay
v[0] = 0; // but now we've entered undefined behavior
【讨论】:
如果您必须防止 const 被丢弃,并且不介意(巨大的)性能损失,您可以返回向量的副本。这样,调用者可以以他们想要的任何方式更改它,而不会影响私有向量。只需按值而不是引用返回。 “以未定义的行为结束”:不完全是,因为v
首先没有声明为 const。
@Arkadiy:它已经通过导致未定义的行为得到保护。没有人应该说或做更多的事情;欲入未定界,必亡。
@GMan 正如 AraK 所说,如果将指向/引用的对象声明为 const,则只有 UB 才能抛弃 const-ness。丢弃指针上的 const 或对本身不是 const 的对象的引用是完美定义的,尽管通常表明设计不好。
它可能是糟糕的设计。为了与糟糕的设计进行交互,也可能需要它。【参考方案3】:
我知道这是一篇相当老的帖子,但在搜索“c++ 只读向量”时,它是谷歌搜索结果中排名靠前的结果之一。这就是为什么我想发布我的方法。
如果您希望容器本身是 const 而不是它的元素,您可以使用类似于此的方法:
template<class Container>
class Enumerable
public:
Enumerable(Container& container) : _container(container)
auto begin() const return _container.begin();
auto end() const return _container.end();
const Container& GetContainer() const return _container;
const Container* operator->() const return &_container;
private:
Container& _container;
;
这样,您可以迭代容器并修改其元素,同时确保容器本身保持不变。您可能希望通过专门化该类来公开容器的更多功能,例如向量通过提供索引运算符。
我不完全确定公开这样的容器是否是好的设计,但在某些情况下它绝对是一种有用的模式。
【讨论】:
【参考方案4】:这是正确的方法,除非用户使用const_cast
来消除常量。
【讨论】:
【参考方案5】:与其返回对向量的引用,不如返回一个包装向量的新类型(包含对向量的 const 引用)并仅公开您希望允许调用者访问的功能。我猜这并不多,因为您想防止向量的可变性。
【讨论】:
【参考方案6】:一般来说这是不好的做法。您正在向调用者公开您的内部实现。您最好返回包装类实例(前面提到过)或公开获取项目或迭代器的函数(类型定义以匹配您的实现)
【讨论】:
只读向量不公开任何内容。该函数对调用者隐藏底层表示。证据是,如果有必要,基础表示可能会在未来的某个时候发生变化。只要公共接口没有改变,调用者就不会受到改变的影响。这实际上是良好实践的关键属性。只读向量也比编写自定义迭代器好得多,因为 STL 对象具有丰富的接口,包括迭代器、访问操作和容量查询。不要重新发明***。【参考方案7】:所以基本上,使用“const &”应该向任何 C++ 程序员表明:你真的不应该修改它。如果您真的很偏执,则必须克隆向量。
【讨论】:
以上是关于如何返回向量的“只读”副本的主要内容,如果未能解决你的问题,请参考以下文章