c++的编译器是非常智能的!当你声明一个空类empty class,如果你的代码有用到这个empty class时,编译器会默默的为你编写一些基本的函数。 那么究竟编译器自己添加的函数都有哪些呢?构造函数,析构函数,一个copy构造函数和一个copy assignment操作符。举个例子来说明一下,如果你写下:
class empty{};
就好像你写下这样的代码:
class Empty { public: Empty(){ ... } //default 构造函数 ~Empty(){ .... } //析构函数 Empty(const Empty & rhs) { ... } //copy 构造函数 Empty & operator=(const Empty & rhs) { ... } //copy assignment 操作符 };不过需要有一点值得注意:只有当这些函数被调用的时候,他们才会被编译器创建出来。如下所示:
Empty e1; //default构造函数 Empty e2(e1); //copy构造函数 e2 = e1; //copy assignment操作符default构造函数和析构函数主要是给编译器一个地方用来放置“藏身幕后”的代码,像是调用base classes和non-static成员变量的构造函数和析构函数。像是调用基类和非静态成员变量的构造函数和析构函数(要不然它们该在哪里被调用呢O(∩_∩)O~)。注意:编译器产生的析构函数是个non-virtual,除非这个类的基类自身声明有virtual析构函数。
如果你不想用默认的构造函数,那么你可以自己手工创建构造函数,这是就会遮盖掉默认构造函数,不再允许调用默认的构造函数。
copy构造函数和copy assignment操作符都是属于copy操作,编译器创建的版本只是单纯地将来源对象的每一个非静态成员变量拷贝到目标对象。考虑下面的代码:
template<typename T> class NameObject { public: NameObject(const char * name, const T& value); NameObject(const std::string & name, const T& value); ~NameObject(); .... private: std::string nameValue; T objectValue; }; NameObject<int> no1("test string", 2); NameObject<int> no2(no1);此时no2.nameValue以no1.nameValue为实参,nameValue是string类型,所以会no2.nameValue会调用string的copy函数进行赋值
no2.objectValue是int类型,会直接拷贝no1.objectValue的每个bits进行赋值。
但是并不是所有情况编译器都可以生成operator=的方法,不满足的情况主要包括下面两种:
待赋值的成员变量中包含引用待赋值的成员变量中包含const变量聪明的你想必已经想到了!对了, c++并不允许“让reference改指向不同对象”。同时,对一个const成员进行赋值也是个bad idea!
如果你打算在一个含有reference成员的class内支持赋值操作符,你必须自己定义copy assignment操作符。
请记住:
[x] 编译器可以暗自为class创建default构造函数,copy构造函数,copy assignment操作符,以及析构函数。