【问题标题】:How to check if weak_ptr is empty (non-assigned)?如何检查weak_ptr是否为空(未分配)?
【发布时间】:2018-01-12 09:45:17
【问题描述】:

有没有办法区分已分配(可能已过期)的weak_ptr 和未分配的。

weak_ptr<int> w1;
weak_ptr<int> w2 = ...;

我了解以下针对未转让或到期的检查,但是否有(更便宜的?)仅针对未转让的检查?

if (!w.lock()) { /* either not assigned or expired */ }

【问题讨论】:

  • 您可以使用expired,但 AFAIK 无法区分。
  • 可能模拟std::optional的东西

标签: c++ c++11 weak-ptr


【解决方案1】:

您可以使用两个对owner_before 的调用来检查与默认构造(空)弱指针是否相等:

template <typename T>
bool is_uninitialized(std::weak_ptr<T> const& weak) {
    using wt = std::weak_ptr<T>;
    return !weak.owner_before(wt{}) && !wt{}.owner_before(weak);
}

这只会在w{} "==" weak 时返回true,其中"==" 比较所有者,并且根据en.cppreference.com

顺序是这样的,两个智能指针只有在它们都是空的或者它们都拥有相同的对象时才比较等价,即使 get() 获得的指针的值不同(例如,因为它们指向不同的子对象在同一个对象内)。

由于默认构造函数构造了一个 empty 弱指针,因此只有在 weak 也是 empty 时才能返回 true。如果weak 已过期,这将不会返回true

查看生成的程序集(经过优化),这似乎非常优化:

bool is_uninitialized<int>(std::weak_ptr<int> const&):
        cmp     QWORD PTR [rdi+8], 0
        sete    al
        ret

...与检查weak.expired()相比:

bool check_expired(std::weak_ptr<int> const&):
        mov     rdx, QWORD PTR [rdi+8]
        mov     eax, 1
        test    rdx, rdx
        je      .L41
        mov     eax, DWORD PTR [rdx+8]
        test    eax, eax
        sete    al
.L41:
        rep ret

... 或 returning !weak.lock()(约 80 行汇编)。

【讨论】:

  • 很棒的解决方案 + 验证。
  • 确实是好答案。一个相当晦涩的技巧,但它至少可以工作。 +1
【解决方案2】:

使用 std::weak_ptr::expired()

#include <iostream>
#include <memory>

//declare a weak pointer
std::weak_ptr<int> gw;

void f()
{
    //check if expired
    if (!gw.expired()) {
        std::cout << "pointer is valid\n";
    }
    else {
        std::cout << "pointer  is expired\n";
    }
}

int main()
{
    f();
    {
        auto cre = std::make_shared<int>(89);
        gw = cre;
        f();
    } 

    f();
}

输出

pointer  is expired
pointer is valid
pointer  is expired
Program ended with exit code: 0

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 2017-11-15
相关资源
最近更新 更多