C++:Copy & Reference Count
浅拷贝、深拷贝通常,我们会按如下方式书写拷贝构造函数: class LiF { public: LiF(int _lif = 0) : lif(_lif) {} // 默认构造函数 LiF(const LiF& l) : lif(l.lif) {} // 拷贝构造函数 private: int lif; }; 这是正确的。但是,如果数据成员包含指针类型的话,这种写法就很危险了。 class LiF { public: LiF() { lif = new int(0); } // 为lif动态分配内存 LiF(const LiF& l) : lif(l.lif) {} // 拷贝构造函数 ~LiF() { // 析构函数 delete lif; // 释放分配给lif的资源 lif = nullptr; // 置空 } private: int* lif; }; LiF l1; LiF l2(l1); // 程序结束析构l2时,程序将崩溃 在拷贝 为了防止指针类型的数据成员出现野指针错误,对应地便有了深拷贝操作,即在拷贝对象内容的同时为拷贝的内容分配新的资源。 class LiF { public: LiF() { lif = new int(0); } // 为lif动态分配内存 LiF(const LiF& l) : lif(new int(*l.lif)) {} // 深拷贝构造函数 ~LiF() { // 析构函数 delete lif; // 释放分配给lif的资源 lif = nullptr; // 置空 } private: int* lif; }; LiF l1; LiF l2(l1); 注意到,在上面的拷贝构造函数中,我们为新对象的 类的行为从上面的例子可以得到两种抽象的类行为:行为像值、行为像指针。 行为像值的类即类提供的构造函数是深拷贝,类的每个对象都有自己的一份拷贝。对于这样的类,它显然需要:一个深拷贝构造函数、一个深拷贝赋值运算符重载、一个可以释放成员占用的资源的析构函数。 class LiF { public: LiF(const int& _lif = 0): lif(new int(_lif)) {} LiF(const LiF& l) : lif(new int(*l.lif)) {} LiF& operator= (const LiF& l) { lif = new int(*l.lif); return *this; } ~LiF() { delete lif; lif = nullptr; } private: int* lif; }; 行为像指针的类即类提供的是浅拷贝,但由于可能有多个对象成员值相同一段内存,所以我们不能在析构时简单地释放资源。为了解决浅拷贝带来的野指针问题,需要引入一种技术——引用计数(reference count)。这也是C++11的智能指针shared_ptr的实现。 引用计数:
class LiF { public: LiF(const int& _lif = 0): lif(new int(_lif)),referenceCount(new unsigned(1)) {} LiF(const LiF& l) : lif(new int(*l.lif)) {} LiF& operator= (const LiF& l) { ++ *l.referenceCount; if (-- *referenceCount == 0) { delete lif; delete referenceCount; } lif = l.lif; referenceCount = l.referenceCount; return *this; } ~LiF() { if (-- *referenceCount == 0) { delete lif; delete referenceCount; } } private: int *lif; unsigned *referenceCount; }; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |