通过std::weak_ptr间接修改const对象是否属于未定义行为?
关于自存weak_ptr实现类共享指针时的常量性丢失与未定义行为问题
我在检查代码时发现一种模拟std::enable_shared_from_this的旧实现:在类内部保存指向自身的std::weak_ptr,通过静态创建函数完成初始化,示例代码如下:
struct X { static auto create() { auto ret = std::shared_ptr<X>(new X); ret->m_weak = ret; return ret; } // 使用 m_weak.lock() 访问对象 //... private: X() {} std::weak_ptr<X> m_weak; };
随后我注意到这种实现存在常量性问题:
struct X { static auto create() { auto ret = std::shared_ptr<X>(new X); ret->m_weak = ret; return ret; } void indirectUpdate() const { m_weak.lock()->val = 1; } void print() const { std::cout << val << '\n'; } private: X() {} std::weak_ptr<X> m_weak; int val = 0; }; int main() { auto x = X::create(); x->print(); x->indirectUpdate(); x->print(); }
这段代码里,indirectUpdate()是const成员函数,按规则不应修改对象,但实际却能修改。原因是在const方法中,std::weak_ptr.lock()仍返回非const的std::shared_ptr<>,从而可以间接修改对象。而std::enable_shared_from_this不会有这个问题——它的shared_from_this在const方法中会返回指向const对象的shared_ptr。
我不确定这段代码是否属于未定义行为(UB),想寻求解答。
更新说明
之前的表述不够准确,我想说明的是:即使持有指向const对象的shared_ptr,也会通过这种方式丢失常量性,示例代码如下:
struct X { static auto create() { auto ret = std::shared_ptr<X>(new X); ret->m_weak = ret; return ret; } void show() const { std::cout << "const \n";} void show() { std::cout << "non-const\n";} void indirectUpdate() const { show(); m_weak.lock()->show(); m_weak.lock()->val = 1; } void print() const { std::cout << val << '\n'; } int val = 0; private: X() {} std::weak_ptr<X> m_weak; }; int main() { // 这里持有const指针 std::shared_ptr<const X> x = X::create(); x->print(); x->indirectUpdate(); x->print(); }
程序输出为:
0 const non-const 1
可见常量性已丢失,想确认该行为是否属于未定义行为。
内容的提问来源于stack exchange,提问作者Afshin
相关产品推荐
相关产品推荐

