【发布时间】:2022-11-15 04:56:26
【问题描述】:
当我今天检查一些代码时,我注意到了一种实现std::enable_shared_from_this 的旧方法,方法是在构造函数中为self 保留std::weak_ptr。像这样的东西:
struct X {
static auto create() {
auto ret = std::shared_ptr<X>(new X);
ret->m_weak = ret;
return ret;
}
// use m_weak.lock() to access the object
//...
private:
X() {}
std::weak_ptr<X> m_weak;
};
但是后来我想到了关于这个对象的 constness 的事情。检查以下代码:
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 方法,它不应该更新我们的对象,但实际上它会更新。因为 std::weak_ptr.lock() 返回一个非 const shared_ptr<>,即使该方法是 const。因此,您将能够在 const 方法中间接更新您的对象。这不会发生在 std::enable_shared_from_this 的情况下,因为 shared_from_this 返回一个共享指针到常量引用const 方法中的对象。我想知道这段代码是否是 UB。我觉得应该是,但我不确定。任何想法?
更新:
抱歉,我的问题似乎没有正确传达。我的意思是即使我们有一个 const 指针,我们也会通过这个方法失去那个 const 性。以下代码显示:
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() {
// Here we have a const pointer
std::shared_ptr<const X> x = X::create();
x->print();
x->indirectUpdate();
x->print();
}
输出如下:
0
const
non-const
1
这表明失去了常数。
【问题讨论】:
-
您正在修改的对象不是
const。 -
它与外部代码没有区别
m_weak.lock()->val = 1;(忽略私有)
标签: c++