假设我有一个带有int指针成员变量"i"的结构"s".我在s的默认构造函数中为i分配内存.稍后在代码的其他部分中,我将一个s值的实例传递给某个函数.我在这里做一个浅色的副本吗?假设我没有为s实现任何复制构造函数或赋值运算符或任何东西......只是默认的构造函数.
为了跟进@ [don.neufeld.myopenid.com]所说的内容,它不仅是一个浅层副本,而且是(请选择)内存泄漏或悬空指针.
// memory leak (note that the pointer is never deleted) class A { B *_b; public: A() : _b(new B) { } }; // dangling ptr (who deletes the instance?) class A { B *_b; public: A() ... (same as above) ~A() { delete _b; } };
要解决此问题,有几种方法.
始终在使用原始内存指针的类中实现复制构造函数和operator =.
class A { B *_b; public: A() ... (same as above) ~A() ... A(const A &rhs) : _b(new B(rhs._b)) { } A &operator=(const A &rhs) { B *b=new B(rhs._b); delete _b; _b=b; return *this; };
毋庸置疑,这是一个巨大的痛苦,并且有很多微妙的事情要做对.我甚至都不确定我是在这里做到的,而且我已经完成了几次.不要忘记你必须复制所有成员 - 如果你以后添加一些新成员,不要忘记添加它们!
在类中创建复制构造函数和operator = private.这就是"锁门"的解决方案.它简单有效,但有时过度保护.
class A : public boost::noncopyable { ... };
永远不要使用原始指针.这很简单有效.这里有很多选择:
使用字符串类而不是原始的char指针
使用std :: auto_ptr,boost :: shared_ptr,boost :: scoped_ptr等
例:
// uses shared_ptr - note that you don't need a copy constructor or op= - // shared_ptr uses reference counting so the _b instance is shared and only // deleted when the last reference is gone - admire the simplicity! // it is almost exactly the same as the "memory leak" version, but there is no leak class A { boost::shared_ptr _b; public: A() : _b(new B) { } };
是的,这是一个浅薄的副本.您现在有两个s副本(一个在调用者中,一个在堆栈中作为参数),每个副本包含指向同一块内存的指针.