3

以下のコードを実行すると、ランタイム エラーが発生します。

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Test
{
public:
    int value;
    Test( )
    {
        value = 1;
    }

    ~Test( )
    {

    }
};

int main() {
    shared_ptr<Test> pTest =  shared_ptr<Test>( new Test( ) );
    std::vector<weak_ptr<Test>> testList;

    testList.push_back( weak_ptr<Test>(pTest) );
    cout << "\n Before Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
        try
        {
            auto p = testList[i].lock();
            cout << "\n Item not null: " << p->value;
        }
        catch (bad_weak_ptr b)
        {
            wcout << L"Null object" << endl;
        }
    }

    pTest.reset( );

    cout << "\n After Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
        try
        {
            auto p = testList[i].lock();
            cout << "\n Item not null: " << p->value;
        }
        catch (bad_weak_ptr b)
        {
            wcout << L"Null object" << endl;
        }
    }

    // your code goes here
    return 0;
}

元の共有ポインターを削除した後、ポインターがまだアクセス可能であるかどうか (そうであってはならない) を見つけようとしていました。

4

2 に答える 2

2

Lock は null をチェックせず、weak_ptr を共有ポインターに昇格させます。オブジェクトが削除されたときにスローするのではなく、null を返します。

これはあなたがすべきことです。

#include <iostream>
#include <vector>
#include <memory>

using namespace std;

class Test
{
public:
    int value;
    Test( )
    {
        value = 1;
    }

    ~Test( )
    {

    }
};

int main() {
    shared_ptr<Test> pTest =  shared_ptr<Test>( new Test( ) );
    std::vector<weak_ptr<Test>> testList;

    testList.push_back( weak_ptr<Test>(pTest) );
    cout << "\n Before Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
      auto p = testList[i].lock();
        if (p)
        {

            cout << "\n Item not null: " << p->value;
        }
        else
        {
            wcout << L"Null object" << endl;
        }
    }

    pTest.reset( );

    cout << "\n After Deletion";
    for (unsigned int i=0; i < testList.size(); i++)
    {
      auto p = testList[i].lock();
        if (p)
        {

            cout << "\n Item not null: " << p->value;
        }
        else
        {
            wcout << L"Null object" << endl;
        }
    }

    // your code goes here
    return 0;
}

明確にするために、pTest のリセット後に test_list>lock を実行すると、NULL を含む shared_ptr が取得されます。これは明らかなセグメンテーション違反です((Test*)NULL)->valuep->value

weak_ptr を持つことの要点は、ユーザーがスコープ外になる可能性のあるオブジェクトへの参照を安全に取得できるようにすることです。例外は低速であるため、例外はこれに適したメカニズムではありません。また、weak_ptr の親がスコープ外になった場合、必ずしも致命的なエラーになるとは限りません。そのため、メカニズムは lock であり、プロモートされたときに新しいカウントされた参照を返すか、所有権レベルをプロモートできなくなった (親が期限切れになった) 場合は NULL を返します。

于 2014-04-02T21:26:38.197 に答える
1

物事がどのように機能するかについて仮定する代わりに、ドキュメントを読むことができます。

lock例外をスローして nullpointer を通知しません。nullpointer を返します。

そう、

        auto p = testList[i].lock();
        if( p != nullptr )
        {
            cout << "\n Item not null: " << p->value;
        }
        else
        {
            cout << "\n Item is null." << endl;
        }
于 2014-04-02T21:27:08.790 に答える