说我有这个班:
#include <vector>
using namespace std;
class Bag
{
vector<int*> items;
public:
void addItem(int* i)
{
items.push_back(i);
}
const vector<int*> getItems() const
{
return items;
}
};
问题是我想阻止更改参数项中指针指向的值。但是使用从getItems
返回的向量,我可以更改指向的值。
现在,为了解决这个问题,我可以将参数项声明为vector<const int*>
但是我无法更改我的类中的值。
有没有其他方法来保护值,但仍然没有在items声明中使用const?
答案 0 :(得分:5)
正如 @KerrekSB 指出的那样,您需要重建结构,将元素的类型更改为常量:
std::vector<const int*> getItems() const {
return std::vector<const int*>(items.begin(), items.end());
}
此处vector<const int*>
的构造函数使用从int*
到const int*
的隐式转换。您不能在此处返回items
,因为vector<T>
在{T}上为invariant。这直接意味着无法从vector<int*>
转换为vector<const int*>
通过类型演员。
解决你的意见:
这是唯一的方法吗?我觉得创建副本效率很低。
对于副本,它只复制指针数据,因此每个元素通常为8个字节。对于指向较大结构的指针向量,它通常可以忽略不计,但对于int
s的向量,它确实是一个相当大的开销。
这给我们带来了一个问题:为什么你首先存储指针?只需存储vector<int>
,然后您就可以向其返回const&
。
答案 1 :(得分:5)
如果您想避免复制并允许对std::vector
元素进行只读访问,则可以提供将const_iterator
放入容器的功能:
class Bag
{
vector<int*> items;
public:
void addItem(int* i)
{
items.push_back(i);
}
//could just be called begin if that gives the correct idea
vector<int*>::const_iterator itemsBegin() const
{
return std::cbegin(items);
}
vector<int*>::const_iterator itemsEnd() const
{
return std::cend(items);
}
};
然后,您将使用该迭代器遍历Bag
内容,而不是获取整个vector
项。如果您提供了begin
和end
功能,那么您甚至可以使用基于范围的for循环。