【发布时间】:2017-07-07 16:32:17
【问题描述】:
我正在编写一个 CustomVector 类,内部使用标准向量存储数据:
template <class T>
class CustomVector {
friend class CustomVector_ref<T>;
public:
...
private:
std::vector<T> _data;
};
然后,为了从 CustomVector 中提取子向量,我使用了一个类来存储指向每个数据元素的指针:
template <class T>
class CustomVector_ref {
public:
//Returns the value stored in CustomVector
//and pointed-to by _data_ref
T& operator[] (size_t id) { return *_data_ref[id] }
const T& operator[] const (size_t id) { return *_data_ref[id] }
...
private:
std::vector<T*> _data_ref;
};
现在,为了说明我的问题,考虑构建对 CustomVector 的所有元素的引用的简单构造函数就足够了
template<class T>
CustomVector_ref<T>::CustomVector_ref(CustomVector<T>& cv)
{
for (T& el : cv._data)
_data_ref.push_back(&el);
}
这很好,但如果我有一个 const CustomVector,我还需要定义构造函数:
template<class T>
CustomVector_ref<T>::CustomVector_ref(const CustomVector<T>& cv)
{
for (const T& el : cv._data)
_data_ref.push_back(const_cast<T*>(&el));
}
这也可以,但如果 CustomVector_ref 对象未声明为 const,则使用非常量运算符 [] 可以将数据写入 const CustomVector 对象。
const CustomVector<int> cv(...) //CostumVector is somehow constructed,
//that does not matter now
std::cout<<cv[0]<<std::endl; //output 1 for example
CustomVector_ref<int> cvr(cv)
cvr[0] = 2;
std::cout<<cv[0]<<std::endl; //now cv[0] stores 2
可以避免这种行为吗?
我注意到标准向量也会发生这种情况,例如
const std::vector<int> v(1,1);
std::vector<int*> vp;
vp.push_back(const_cast<int*>(&v[0]));
*vp[0] = 2;
std::cout<<v[0]<<std::endl; // now v[0] stores 2, not 1
所以,由于这是标准 C++,我不会费心去修复我的 CustomVector,但如果有一个(不太复杂的)解决方案会很高兴。
【问题讨论】:
-
您需要考虑一个简单的事实,即标准库容器定义了两个不同的迭代器类:
iterator和const_iterator。这是有充分理由的,而您刚刚发现了这个原因。你的情况完全类似。您需要实现两个不同的引用,一个可变引用和一个const引用。为了获得额外的荣誉,可变引用应该可以转换为const引用,因此它可以传递给以const引用作为参数的函数。 -
犹豫是否将其标记为欺骗,但这是密切相关的stackoverflow.com/questions/44882363/…
-
使用
CustomVector_ref<const int>怎么样?这种方式不需要 const_cast -
@geza 这会起作用,在这种情况下,如果没有 const_cast,就不可能像任何人所期望的那样写入 const CustomVector 对象。但我认为将 CustomVector_ref
声明为 CustomVector 的引用更为自然,即使它是 const。但我会考虑你的建议。 -
@SamVarshavchik:为什么不回答这个问题?
标签: c++ pointers vector constants