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它分配后不得使用(直到您再次分配或重置它)。


尽管这种智能指针是非常可取的东西,但这种行为是如此尴尬,这表明该语言中缺少某些东西。正确的解决方案需要右值引用,而 newunique_ptr试图解决与 相同的问题auto_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;您正在删除当前指向的对象ptr2,该对象现在指向先前指向的对象ptr1ptr1已将自身设置为指向null,因为这是auto_ptron 副本的语义。然后,您尝试取消对 null 的引用,并且很幸运地发生了崩溃并发现您的代码是错误的。

于 2013-01-01T12:50:03.107 回答