我正在详细学习c++特殊成员。
我正在摆弄一些代码并尝试不同的方法,然后遇到了这个:
#include <iostream>
#include <string>
using namespace std;
class Example5 {
public:
string* ptr;
public:
Example5 (const string& str) : ptr(new string(str)) {}
~Example5 () {delete ptr;}
// copy constructor:
Example5 (const Example5& x) : ptr(x.ptr) {}
};
int main () {
Example5 foo ("Example");
Example5 bar (foo);
cout << foo.ptr << endl << bar.ptr;
return 0;
}
下面的代码显示了一个具有预期结果的对象的浅拷贝:
0x505348
0x505348
虽然这段代码似乎没有执行浅拷贝:
// copy constructor: deep copy
#include <iostream>
#include <string>
using namespace std;
class Example5 {
public:
string* ptr;
public:
Example5 (const string& str) : ptr(new string(str)) {}
~Example5 () {delete ptr;}
// copy constructor:
Example5 (const Example5& x) : ptr((*this).ptr) {}
};
int main () {
Example5 foo ("Example");
Example5 bar (foo);
cout << foo.ptr << endl << bar.ptr;
return 0;
}
结果如下:
0x505348
0x505278
*this
不只是指向对象和它的成员吗?
我正期待同样的结果。
您是正确的,第一段代码只是简单地将ptr
的值从一个对象复制到另一个对象。当两个对象超出作用域并被销毁时,这将导致问题,因为它们的析构函数都将尝试delete
相同的内存。
在第二段代码中,用(*this).ptr
初始化ptr
实际上是一个无操作(实际上是未定义行为(因为不能从未初始化的变量中读取值)。由于您是用自身初始化ptr
,因此它的最终值将是indeterminate。
ptr
的正确代码是:
Example5 (const Example5& x) : ptr(new string(*(x.ptr))) {}
或者,在c++ 11及以后的版本中,您可以将委托给接受string
的其他Example5
构造函数:
Example5 (const Example5& x) : Example5 (*(x.ptr)) {}
另外,请确保添加一个可行的副本分配operator=
到Example5
,以完成规则3的实现。