分配时是否可以保留对象的常量?考虑一个持有动态内存指针的类,在分配时需要软拷贝。 (有一些更复杂的逻辑,包括引用计数,但它与问题无关)。
class Vec {
private:
int *data_; // dynamic array
public:
int * Data() { return data_;} // access for modification
const int * Data() const { return data_;} // read only access
Vec subVec(int pos) { // create writable submat
Vec ret;
ret.data_ = &data_[pos];
return ret;
}
const Vec subVec(int pos) const { // create read only submat
Vec ret;
ret.data_ = &data_[pos];
return ret;
}
};
void processVec(const Vec & src) {
src.Data()[0] = 1; // not allowed, since src const
Vec subVec = src.subVec(2); // call const version of subVec and create
// a soft copy - wrapper for a part of array.
// Assignment creates a copy, which removes constness
subVec.Data()[0] = 1; // allowed! Since subVec is a copy, but modifies
// identical dynamic memory from the wrapped src!
}
我希望subVec.Data()[0] = 1;
失败,因为它应该保持const。
答案 0 :(得分:2)
您的问题是,您正在定义一个指向某个对象的智能指针,但是您将智能指针的常量(类似于Foo* const bar;
)与对象的常量(类似于const Foo* bar;
)混淆)。你需要的是将指针的常量与对象的常量分开。
通过使用两个智能指针类而不是一个智能指针类,可以相对容易地实现:基类,实现const
对象的智能指针,以及实现非智能指针的派生类const
对象。
有了这个,你总是可以降级你的智能指针到“const”基类,make copy free“const”副本等等。你甚至可以在派生的非“const”智能指针类中添加一个构造函数。采用“const”基类的智能指针来制作数据的深层副本。
答案 1 :(得分:1)
在使用const或非const对象时,我会通过创建不同的返回类型来模仿iterator
和const_iterator
习语。这里有一个示例,它实现了对subVec
的const调用的不同类型:
class Vec {
// ...
public:
// ...
const int * Data() const { return data_;} // read only access
Vec subVec(int pos) { // create writable submat
Vec ret;
ret.data_ = &data_[pos];
return ret;
}
class SubVec
{
private:
const int* data_;
public:
SubVec(const int* data) : data_(data) {}
const int * Data() const { return data_;} // read only access
};
const SubVec subVec(int pos) const { // create read only submat
SubVec ret(&data_[pos]);
return ret;
}
};
这将生成the error you want in the const case和will compile in the non const case。使用auto
可以为代码用户编写更简单的代码。
答案 2 :(得分:0)
IIUC,const或非const的元素在运行时分配,因此类型系统(它是静态的)无法帮助你。您需要为每个元素存储一些布尔标志,并对赋值执行运行时检查以查看是否允许。