c++ - `weak_ptr::expired` 对象 dtor 中的行为

标签 c++ c++11 c++14 shared-ptr weak-ptr

考虑以下代码:

#include <iostream>
#include <memory>
using namespace std;

class T;

std::weak_ptr<T> wptr;

class T
{
public:
    T() {  }
    ~T() {
        std::cout << "in dtor" << std::endl;
        std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
    }
};

int main() {
    {
        auto ptr = std::make_shared<T>();
        wptr = ptr;
        std::cout << (wptr.expired() ? "expired" : "not expired") << std::endl;
    }
    return 0;
}

在这段代码中,我试图找出 weak_ptr 是否在对象销毁阶段过期。似乎是这样。输出是:

not expired
in dtor
expired

我使用 gcc-5.1 和 ideone .

现在,我有另一个问题。我找不到任何说明这是标准行为的文档。是否保证以这种方式工作,总是

最佳答案

Now, I have another problem. I couldn't find any documentation stating that this is the standard behavior. Is it guaranteed to work this way, always?

没有。事实上,正如 LWG issue 2751 所提出的,它在标准中没有被详细说明。 .

The C++14 standard contains no language that guarantees the deleter run by a shared_ptr will see all associated weak_ptr instances as expired. For example, the standard doesn't appear to guarantee that the assertion in the following snippet won't fire:

std::weak_ptr<Foo> weak;
std::shared_ptr<Foo> strong{
  new Foo,
  [&weak] (Foo* f) {
    assert(weak.expired());
    delete f;
  },
};

weak = strong;
strong.reset();

It seems clear that the intent is that associated weak_ptrs are expired, because otherwise shared_ptr deleters could resurrect a reference to an object that is being deleted.

Suggested fix: 23.11.3.2 [util.smartptr.shared.dest] should specify that the decrease in use_count() caused by the destructor is sequenced before the call to the deleter or the call to delete p.

上面链接的 ~shared_ptr() 的当前措辞只是说明调用了删除器,并带有非规范性说明,即共享所有权的实例数量减少了。

虽然调用删除器时的意图可能是 weak.expired(),但依赖它是有问题的。只有在shared_ptr 被销毁后 不再共享所有权的自信声明才是合理的 - 问这个问题 销毁过程中有点奇怪.

关于c++ - `weak_ptr::expired` 对象 dtor 中的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41851520/

相关文章:

C++ 测试 - 符号位 1 是否总是表示负数?

c++ - 我希望在对右值的引用上调用基于右值的函数......如果有这样的事情

c++ - 我可以避免在一系列函数调用中使用模板消歧器吗?

c++ - 无锁有界堆栈 C++11 原子

c++ - 没有大于 k 的质因数的正数

c++ - ODR 使用转发的 constexpr 参数?

c++ - std::array 大小在类包装器实例化时设置

c++ - 类中的 C++ 方法定义是否必须指定返回类型?

c++ - 用于存储通用 lambda 的通用 std::function

c++ - 函数中二维字符数组的长度