声明:
- 文中内容收集整理自《Effective C++(中文版)第三版》,版权归原书所有。
- 本内容在作者现有能力的基础上有所删减,另加入部分作者自己的理解,有纰漏之处敬请指正。
条款05:了解C++默默编写并调用哪些函数
Know what functions C++ silently writes and calls.
直接进入正题。
如果没有声明,编译器会默认声明:默认构造函数、拷贝构造函数、拷贝赋值运算符、析构函数等,所有这些函数都是public而且默认inline。
注意,编译器产出的析构函数(即默认析构函数)是个non-virtual(见条款7),除非这个class的base class自身声明有virtual析构函数。
默认拷贝构造函数和拷贝赋值运算符也只是单纯地将来源对象的每一个non-static成员变量拷贝到目标对象。
当类成员含const或者reference成员,默认赋值运算符不合法,eg:
template<typename T>
class NameObject
{
public:
NameObject(std::sting &name, const T& value);
...
private:
std::string& nameValue;
const T objectValue;
};
//考虑下面会发生什么事情
std::string newDog("Persephone");
std::string oldDog("Satch");
NameObject<int> p(newDog, 2);
NameObject<int> s(oldDog, 36);
p = s;
思考以上赋值语句p=s,复制之后p.nameValue应该指向s.nameValue所指的那个string吗?也就是说reference自身可以被改动吗?答案是,不可以。因为C++不允许“让reference改指不同的对象”。
面对这个问题,C++的响应是拒绝编译那一行的赋值操作。面对内含const成员的classes编译器的反应也一样。还有另一种情况,如果某个base classes的拷贝赋值运算符被声明为private,那么编译器会拒绝为其derived classes生成一个拷贝操作运算符。
请记住:
编译器可以暗自为class创建default构造函数、copy构造函数、copy assignment运算符以及析构函数。