包含shared_ptr的对象的Const正确性
Const correctness with objects containing shared_ptr
考虑对象:
class Obj
{
public:
Obj() : val(new int(1)) {}
int& get() {return *val;}
const int& get() const {return *val;}
private:
std::shared_ptr<int> val;
};
正如预期的那样,当构造对象并进行复制时,它们都可以通过Obj公开的shared_ptr修改相同的值。
Obj nonconst1;
Obj nonconst2(nonconst1);
nonconst2.get() = 2;
cout << nonconst1.get() << ", " << nonconst2.get() << endl;
也可以从一个非const对象复制构造一个const Obj
对象,这似乎做了正确的事情,因为它允许读取但不写入值-正如预期的那样,下面的代码会导致编译错误:
const Obj const1(nonconst1);
const1.get() = 3;
但是可以从const对象复制构造一个非const对象,这样就允许修改该值。
Obj nonconst3(const1);
nonconst3.get() = 3;
对我来说,这感觉不太正确。
是否有一种方法可以防止这种行为,同时仍然允许复制构造函数工作?在我的实际用例中,我仍然希望object的std容器是可能的。
"对我来说这感觉不是const-correct"然而它是:你只是在一个非const Obj
上调用一个非const get
方法。这没什么不对的。
如果你真的需要你所追求的行为,你可以使用像Obj
的const代理这样的东西,但是你的客户端必须能够处理它:
class Obj
{
//...
//original class definition goes here
//...
friend class ConstObj;
};
class ConstObj
{
public:
ConstObj( const Obj& v ) : val( v.val ) {}
const int& get() const { return *val; }
private:
std::shared_ptr<int> val;
};
//usage:
class WorkingWithObj
{
public:
WorkingWithObj();
Obj DoSomethingYieldingNonConstObj();
ConstObj DoSomethingYieldingConstObj();
};
WorkingWithObj w;
Obj nonconst( w.DoSomethingYieldingNonConstObj() );
nonconst.get() = 3;
ConstObj veryconst( nonconst );
veryconst.get() = 3; //compiler error
ConstObj alsoconst( w.DoSomethingYieldingConstObj() );
alsoconst.get() = 3; //compiler error
没有,除非你想存储一个shared_ptr<const int>
,在这种情况下没有人可以作为非const访问它。
这不会破坏const的正确性。val
所指向的整数对象是一个不同的对象,它不被原始对象独占。修改它的值不影响Obj
对象的状态
是否有一种方法可以防止这种行为,同时仍然允许复制构造函数工作?在我的实际用例中,我仍然希望Obj的std容器是可能的。
你可以为从const
对象复制指定一个不同的复制构造函数——这意味着你可以避免复制共享指针,而是用NULL指针创建非const对象,或者你可以对指向的数字进行深度复制。我对做这种事情非常谨慎——根据复制变量的稳定性得到不同的行为是很奇怪的——我担心这会让你很难推断你的程序行为。但是,您必须选择一些行为或接受当前的行为,因为std::vector<>
有时会创建副本-您不能简单地不定义
不,没有……但是,当您可以写入value
(在非const getter中)时,您可以使用COW
, deep-copy
指针。
或者,你可以写两个copy-ctors
(对于ref
做浅拷贝,对于cref
做深拷贝)
A(A& obj) : pointer(obj.pointer) {}
A(const A& obj) : pointer(new int(*obj.pointer)) {}
手动实现Obj
的复制构造函数,然后复制共享指针的内容。这避免了通过nonconst3
修改const1
的内容,因为它们指向不同的int实例。
Obj
的非const实例进行深度复制(这没有问题,并且打算重用旧的共享指针)。为此,必须同时提供const和非const复制构造函数,并且只复制const中的构造函数:
class Obj
{
public:
//...
Obj(Obj &o) : val(o.val) {} // not a deep copy
Obj(const Obj &o) : val(std::make_shared(o.get())) {} // deep copy
//...
}
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 在正确性或良好的代码结构方面,这种动态对象创建看起来如何
- const对象和成员指针的const正确性,构造函数漏洞
- OO 正确性 - 继承层次结构 - 谁创建其他对象使用的对象
- 包含shared_ptr的对象的Const正确性