web-dev-qa-db-ja.com

weak_ptrが空(割り当てられていない)かどうかを確認するにはどうすればよいですか?

割り当てられている(期限切れの可能性がある)weak_ptrと割り当てられていないものを区別する方法はありますか?.

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

次の非割り当てまたは有効期限のチェックについて理解していますが、非割り当てのみの(安価な)チェックはありますか?

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

_owner_before_への2つの呼び出しを使用して、デフォルトで作成された(空の)弱ポインタ​​ーとの等価性をチェックできます。

_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_が所有者を比較する_"=="_の場合、および en.cppreference.com に従ってtrueのみを返します。

順序は、get()によって取得されたポインタの値が異なる場合でも(たとえば、同じ内の異なるサブオブジェクトをポイントしているため)、2つのスマートポインタが両方とも空であるか、両方が同じオブジェクトを所有している場合にのみ、同等に比較されますオブジェクト)。

デフォルトのコンストラクターはemptyウィークポインターを構築するため、これはtrueemptyである場合にのみweakを返すことができます。 trueの有効期限が切れている場合、これはではありませんweakを返します。

生成されたアセンブリ(最適化あり)を見ると、これはかなり最適化されているように見えます。

_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
_

...または !weak.lock() を返します(〜80行のアセンブリ)。

22
Holt

ウィークポインターをパラメーターとして受け入れ、ウィークポインターが期限切れの場合(または、あなたの場合のように割り当てられていない場合)は std :: bad_weak_ptr 例外を発生させる共有ポインターの作成を試みることができます。

#include <memory>
#include <iostream>
int main(){
    // with an assigned pointer
    std::shared_ptr<int> p1(new int(42));
    std::weak_ptr<int> w1(p1);
    try {
        std::shared_ptr<int> p2(w1);
    }
    catch (const std::bad_weak_ptr& e) {
        std::cout << e.what() << '\n';
    }
    // with a non assigned pointer
    std::shared_ptr<int> p2(new int(42));
    std::weak_ptr<int> w2;
    try {
        std::shared_ptr<int> p2(w2); // raises an exception
    }
    catch (const std::bad_weak_ptr& e) {
        std::cout << "Ptr 2: " << e.what() << '\n';
    }
}
1
Ron

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
1
Hariom Singh