#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)
答案 0 :(得分:4)
旧的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);
答案 1 :(得分:1)
执行ptr2 = ptr1;
时,您正在删除ptr2
当前指向的对象,该对象现在指向ptr1
先前指向的对象。 ptr1
已将自己设置为指向 null ,因为这是副本上auto_ptr
的语义。然后,您尝试取消引用null,并且很幸运地遇到崩溃并且认为您的代码错误。