简体   繁体   English

使用std :: weak_ptr和std :: shared_ptr进行阴影

[英]Using std::weak_ptr with std::shared_ptr for shadowing

The documentation for std::weak_ptr on cppreference says this cppreference上 std::weak_ptr的文档说

Effectively returns expired() ? shared_ptr<T>() : shared_ptr<T>(*this) 有效地返回expired() ? shared_ptr<T>() : shared_ptr<T>(*this) expired() ? shared_ptr<T>() : shared_ptr<T>(*this) , executed atomically. expired() ? shared_ptr<T>() : shared_ptr<T>(*this) ,原子执行。

And my judgement and other SO answers have confirmed that the following is not prone to races 我的判断和其他SO答案已经证实以下内容不容易出现种族

int main() {
    auto s_ptr = std::make_shared<T>(...);
    auto w_ptr = std::weak_ptr<T>{s_ptr};

    auto one = std::thread{[&]() {
        auto ptr = w_ptr.lock();
        if (ptr) { ... }
    }};
    s_ptr = std::make_shared<T>(...);

    one.join();
}

However can this reliably be used to shadow computation in a program? 但是,这可以可靠地用于程序中的影子计算吗? By shadowing I mean something like this 阴影我的意思是这样的

auto s_ptr = std::make_shared<T>(...);
auto w_ptr = std::weak_ptr<T>{s_ptr};

// thread one
while (...) {
    auto ptr = w_ptr.lock();
    cout << "Value contained is " << *ptr << endl;
}

// thread two
while (...) {
     // do the heavy computation on the side
     auto new_value = fetch_new_value();

     // then "atomically" swap
     s_ptr = std::make_shared<T>(std::move(new_value));
}

The confusing part here is what .lock() returns. 这里令人困惑的部分是.lock()返回的内容。 Can it return a nullptr ? 它可以返回nullptr吗? All the documentation says is that the operation will be executed atomically. 所有文档都说该操作将自动执行。 Doesn't say what this mutual exclusion means. 不要说这种互斥意味着什么。 Can there be a state in shared_ptr::operator= where the pointer is null? shared_ptr::operator=中是否可以存在指针为空的状态? And can the weak_ptr access this state? 而且weak_ptr可以访问此状态吗? The documentation for shared_ptr::operator= on cppreference does not seem to mention this. 关于cppreference的 shared_ptr::operator=的文档似乎没有提到这一点。

As soon as your shared pointer gets a new value, your weak pointer will start returning nullptr The reason being that the original object gets destroyed as soon as your shared pointer starts pointing to a different object. 一旦共享指针获得新值,弱指针将开始返回nullptr原因是,一旦共享指针开始指向另一个对象,原始对象就会被破坏。

But there will be no undefined behavior exchanging pointers because the handoff is atomic. 但是,因为切换是原子的,所以不会有未定义的行为交换指针。

(Although, dereferencing the nullptr value shared pointer returned by w_ptr.lock() is undefined and will likely crash the program). (尽管,取消引用由w_ptr.lock()返回的nullptr值共享指针是未定义的,可能会导致程序崩溃)。

You would need to get a new weak pointer every time your shared pointer gets reset with a new value. 每当共享指针被重置为新值时,您将需要获得一个新的弱指针。 But whether or not the shared pointer is still pointing at that new value by the time you lock() your weak pointer is anyone's guess. 但是,在您lock()弱指针时,共享指针是否仍仍指向该新值,这是任何人的猜测。

Anything that relates to the control bloc (the reference count) is atomic. 与控制组(参考计数)有关的任何事情都是原子的。 So obtaining a new weak pointer is thread safe but not guaranteed to be pointing at anything (if other threads have access to your shared pointer). 因此,获取新的弱指针是线程安全的,但不能保证指向任何东西(如果其他线程可以访问您的共享指针)。

This code can execute UB: 此代码可以执行UB:

auto s_ptr = std::make_shared<T>(...);
auto w_ptr = std::weak_ptr<T>{s_ptr};

// thread one
while (...) { // A
  auto ptr = w_ptr.lock(); // B
  cout << "Value contained is " << *ptr << endl; // C
}

// thread two
while (...) {
  // do the heavy computation on the side
  auto new_value = fetch_new_value();

  // then "atomically" swap
  s_ptr = std::make_shared<T>(std::move(new_value)); // X
}

If thread two executed // X before thread one executed // B , weak_ptr no longer refers to any data. 如果第二个线程// X在第一个线程// B之前执行// X ,则weak_ptr不再引用任何数据。

.lock() then returns a "null" shared_ptr , which you proceed to dereference at // C . 然后, .lock()返回一个“空” shared_ptr ,您可以在// C处继续对其取消引用。

If you guarded use of ptr against it being null, there would be no UB apparent. 如果您防止将ptr用作空值,则不会有明显的UB。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 std :: shared_ptr,std :: weak_ptr和控制块 - std::shared_ptr, std::weak_ptr and control block std :: weak_ptr:lock或shared_ptr构造函数? - std::weak_ptr: lock or shared_ptr constructor? 使用 std::shared_ptr/weak_ptr 的简化观察者模式 - simplfied observer pattern with std::shared_ptr/weak_ptr 使用shared_ptr和weak_ptr来管理std :: function safe的生命周期? - Is using shared_ptr and weak_ptr to manage lifetime of std::function safe? 将std :: shared_ptr的容器(std :: vector)过滤到std :: weak_ptr的容器 - Filtering a container ( std::vector ) of std::shared_ptr to a container of std::weak_ptr 对象std :: shared_ptr是否可以通过std :: weak_ptr找到? - Is object std::shared_ptr findable by its std::weak_ptr? std::weak_ptr 和相应的 std::shared_ptr 之间是否存在数据竞争? - Is there any data race between std::weak_ptr and corresponding std::shared_ptr? 没有可行的将std :: weak_ptr转换为std :: shared_ptr的方法调用 - No viable conversion std::weak_ptr to std::shared_ptr for method call 用 std::shared_ptr 和 std::weak_ptr 替换引用存储 - Replace references storage with std::shared_ptr and std::weak_ptr 在信号处理程序中使用`std :: shared_ptr`和`std :: weak_ptr`是否安全? - Is it safe to use `std::shared_ptr` and `std::weak_ptr` in a signal handler?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM