概述:《Efficient C++》第 4 条,了解CPP默认创建并调用的函数

编译器创建的函数

空类:

class Empty{};

编译器默认添加的函数:

// defaultFunc.h
class Empty
{
public:
    // 当程序中未定义以下函数时编译器默认添加
    Empty() {  }                                // 默认构造函数
    Empty(const Empty& rhs) {  }                // 拷贝构造函数
    ~Empty() {  }                               // 析构函数
    Empty& operator=(const Empty& rhs) {  }     // 拷贝赋值操作符函数
};

拷贝构造函数与拷贝赋值操作符函数

拷贝构造函数和拷贝赋值操作符函数,编译器创建的版本只是单纯地将来源对象的每一个非静态成员变量拷贝到目标对象。如下模板类 NamedObject,它允许你将一个名称和类型为 T 的对象产生关联。

// copy.h
#ifndef __COPY_H__
#define __COPY_H__
 
#include <iostream>
 
template<typename T>
class NamedObject
{
public:
    /**
      由于其中声明了一个构造函数,编译器于是不再为它创建默认构造函数。
      这很重要,意味如果你用心设计一个类,其构造函数要求实参,
      你就无须担心编译器会毫无挂虑地为你添加一个无实参构造函数(即默认构造函数)而遮盖掉你的版本。
     */
    NamedObject(const char *name, const T& value) : nameValue(name), objectValue(value) {}
    NamedObject(const std::string& name, const T& value) : nameValue(name), objectValue(value) {}
 
private:
    std::string nameValue;
    T objectValue;
};
 
#endif // __COPY_H__
// main.cpp
#include "copy.h"
 
int main()
{
    /**
      NamedObject 既没有声明拷贝构造函数,也没有声明拷贝赋值操作符函数,
      所以编译器会为它创建那些函数(如果它们被调用的话)。
      现在,看看拷贝构造函数的用法
     */
    NamedObject<int> no1("Smallest Prime Number", 2);
    NamedObject<int> no2(no1);
    return 0;
}

编译器拒绝创建拷贝赋值操作符函数的情况

编译器为 NamedObject<int> 所产生的拷贝赋值操作符函数,其行为基本上与拷贝构造函数如出一辙,但一般而言只有当生出的代码合法且有适当机会证明它有意义,其表现才会如我先前所说。万一两个条件有一个不符合,编译器会拒绝为类产生拷贝赋值操作符函数。

编译器拒绝创建拷贝赋值操作符函数情况:

  • 成员函数为引用类型。
  • 成员函数为常量。