为什么智能指针auto_ptr在那个时候不能被引用

Why the smart pointer auto_ptr cannot be referenced at that time?

本文关键字:候不能 不能 引用 auto 指针 智能 ptr 为什么      更新时间:2023-10-16
#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 donen"<<endl;
    ptr2 = ptr1;
    ptr2->myFunc();
    //ptr1->myFunc();
    cout<<"test 2 donen"<<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)

旧的auto_ptr在复制或分配时具有非常奇怪的行为。它具有传输语义,而不是复制语义。这意味着当你说ptr2 = ptr1;时,ptr1实际上已经改变了:它不再指向任何东西。(当然,ptr2原先指向的东西已经被删除了。)

因此,在你从赋值之后,你不能使用ptr1(直到你再次赋值或者重置它)。


这种行为是如此的尴尬,尽管这样一个智能指针是一个非常可取的东西,这表明语言中缺少了一些东西。正确的解决方案需要右值引用,新的unique_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);

当您执行ptr2 = ptr1;时,您正在删除当前由ptr2指向的对象,该对象现在指向以前由ptr1指向的对象。ptr1将自己设置为指向null,因为这是auto_ptr在副本上的语义。然后尝试取消对null的引用,很幸运地出现了崩溃,并发现代码是错误的。