1
#include <memory>
#include <iostream>

using namespace std;
class MyClass
{
public:
    int i;
    MyClass(int s) {
        i=s;
    }
    ~MyClass() {
        cout<<"This class has been destroied.  "<<i<<endl;
    }
    void myFunc() {
        cout<<"myFunc() done.  "<<i<<endl;
    }
};

int main()
{
    auto_ptr<MyClass> ptr1(new MyClass(1));
    auto_ptr<MyClass>ptr2(new MyClass(2));
    ptr1->myFunc();
    ptr2->myFunc();
    cout<<"test 1 done\n"<<endl;

    ptr2 = ptr1;
    ptr2->myFunc();
    //ptr1->myFunc();
    cout<<"test 2 done\n"<<endl;
}
/*
$ ./a.out 
myFunc() done.  1
myFunc() done.  2
test 1 done

This class has been destroied.  2
myFunc() done.  1
test 2 done
 * */

上記ptr1->myFunc();がコメントアウトされていない場合、結果は以下のようになります。しかし、私はそれを理解することはできません。その時点で ptr1 は破壊されていないと思います...誰がそれをさらに説明するのを助けることができますか?

$ ./a.out 
myFunc() done.  1
myFunc() done.  2
test 1 done

This class has been destroied.  2
myFunc() done.  1
Segmentation fault (core dumped)
4

2 に答える 2

4

古いものauto_ptrは、コピーまたは割り当て時に非常に奇妙な動作をします。コピーのセマンティクスではなく、転送のセマンティクスがあります。これは、あなたが言うよりもptr2 = ptr1;ptr1が実際に変更されたことを意味します。それはもはや何も指していません。(そして、ptr2もともと指していたものはもちろん削除されています。)

したがって、割り当てた後は (再度割り当てるかリセットするまで) 使用ptr1ないでください


このようなスマート ポインターは非常に望ましいものですが、この動作が非常にぎこちないという事実は、言語に何かが欠けていることを示しています。正しい解決策には右辺値参照が必要であり、unique_ptrと同じ問題を解決しようとするnewauto_ptrはより賢明に動作します: コピーまたはコピー代入はまったくできませんが、移動できます— これは言語の新しい部分です:

unique_ptr<MyClass> ptr1(new MyClass), ptr2(new MyClass);

ptr2 = std::move(ptr1);  // now it's clear that ptr1 is no longer usable

assert(!ptr1);
于 2013-01-01T12:50:33.323 に答える
1

これを行うと、以前に が指していたオブジェクトをptr2 = ptr1;現在指している が現在指しているオブジェクトが削除されます。nullを指すように自身を設定しました。これは、コピーのセマンティクスであるためです。次に、null を逆参照しようとすると、幸運にもクラッシュが発生し、コードが間違っていることがわかります。ptr2ptr1ptr1auto_ptr

于 2013-01-01T12:50:03.107 に答える