对待拷贝构造函数和赋值函数的3种境界.doc
文本预览下载声明
对待拷贝构造函数和赋值函数的3种境界
2010-10-29 11:53 by zhenjing, 817 visits, 网摘, 收藏, 编辑
对待拷贝构造函数和赋值函数有3种境界:不写;禁用;正确编写。
1) 不写。不写代码是编程的最高境界。有一种说法:最完美的代码是无以复减的代码。不写的代码永远不会出错,也不需要维护。任何存在的代码都需要维护,只要代码可能变化。
C++的编译器可以提供默认的构造函数、析构函数、拷贝构造函数、赋值函数、一对取址运算符(*, )。C++的默认构造函数仅对内置变量随机赋值,具有不确定性,一般不建议使用默认构造函数;对于析构函数讨论比较多,这里不加讨论。但有一个准则:如果需要编写任一特定的析构函数、拷贝构造函数或者赋值函数,那么你也需要编写其余的两个。
何时不写呢?只要类(包括类中的类变量)不拥有任何资源,那么就可利用编译器的默认版本。常见资源有:内存、文件和端口。任何资源都需要显式的获取和释放,C++的默认拷贝和赋值操作并无法保证正确的资源获取和释放。
如果直接使用编译器版本,最好加注释,让代码阅读者更清楚。
2)禁用。禁用代码将给代码的使用者明确的提示,防止误用。如果你定义的类,并不需要拷贝和赋值,请明确禁用,而不是让使用者误用编译器提供的错误版本。示例:
class T {// …
private: // make T non-copyable
T( const T ); // not implemented
T operator=( constT ); // not implemented
};
3)巧妙正确地写。只要类拥有自己的资源,用户都需要自行编写拷贝构造函数和赋值函数,或者直接禁止(直接使用对象指针或引用,这样的类不具有值属性)。代码示例:
代码
#include iostream#include stringusing namespace std;templateclass T class NamedPtr{public: explicitNamedPtr(const std::string name); //NamedPtr(conststd::string name, T *data); //note:user manages the memory ~NamedPtr(); NamedPtr(constNamedPtr rhs); NamedPtroperator=(const NamedPtr rhs); voidPrint() const;private: std::stringm_name; T*m_data; // can be T or T[]. Atthis example use T only};templateclass TNamedPtrT::NamedPtr(conststd::string name): m_name(name), m_data(NULL){ m_data= new T(); // T must have a defaultconstructor}//templateclass T//NamedPtrT::NamedPtr(conststd::string name, T *data)//: m_name(name)//, m_data(data)//{//}templateclass TNamedPtrT::~NamedPtr(){ deletem_data; m_data= NULL;}templateclass T //Note: copyconstructor wont call other constructors, it will create a new object byitselfNamedPtrT::NamedPtr(constNamedPtrT rhs){ m_data= new T(); // T must have a defaultconstructor *this = rhs; //call assign function to avoid duplicated code}templateclass TNamedPtrTNamedPtrT::operator=(const NamedPtrT rhs){ //1.check assign self. if
显示全部