Effective C++ 条款05_不止于此

了解C++ 默默编写并调用哪些函数

先来看看一个空类

class Empty{
    
     ... };  //  空类

当有对象被创建出来并调用这些函数的时候 C++ 就会产出下面这些函数 :

class Empty {
    
    
public:
	Empty(){
    
    ...};   //默认(default )构造函数
	Empty(const Empty& params){
    
    ...};  // 拷贝(copy)构造函数
	~Empty(){
    
    ...};        //析构函数
	
	Empty& operator=(const Empty& params){
    
    ...};   // copy assignment 操作符
};

下面创建类的对象以及使用:

Empty e1;   // 调用默认构造函数和析构函数
Empty e2(e1);// 调用copy构造函数
e2 = e1;    // 调用 copy assignment 操作符
  • copy 构造函数和 copy assignment 操作符,编译器创建的版本只会单纯地将来源对象的每一个 non-static 成员变量拷贝到目标对象。

下面来看看 copy 构造函数的用法
直接上代码:

#include<iostream>

template <typename T>
class Adg {
    
    
	std::string _name;
	T _value;
public:
	Adg(const char* name, const T& value);  	// 声明构造函数
	Adg(const std::string& name, const T& value);	// 构造函数重载
};
template <typename T>
Adg<T>::Adg(const char* name, const T& value) {
    
        // 定义构造函数
	_name = name;
	_value = value;
}
template <typename T>
Adg<T>::Adg(const std::string& name, const T& value) {
    
    
	_name = name;
	_value = value;
}
int main() {
    
    
	Adg<int> no1("gwww", 2);
	Adg<int> no2(no1);					// 调用 copy 构造函数
	return 0;
}

由于已经显式声明了构造函数,系统不再生成默认构造函数。
下面来看创建类的对象

Adg<int> no1("gwww", 2);
Adg<int> no2(no1);					// 调用 copy 构造函数
  • 由于 _name 的类型为 string, 所以第二条语句执行调用的是第二个为 string 类型的构造函数,并以 no1._name 和 no1._value 为实参进行 copy 构造完成初始化。
    若进行如下操作:
Adg<int> no3 = no1;		//调用 copy assignment 操作符

编译器为 Adg所生出的 copy assignment 操作符行为和 copy 构造函数的行为一样。
但有时候编译器会拒绝为 class 生出 operator=。
看代码

#include<iostream>

template <typename T>
class Adg {
    
    
	std::string& _name; 			//改为了引用类型
	const T _value;					//加了const
public:
	Adg(std::string& name, const T& value);	// 构造函数重载
	// 下面创建对象使用变量初始化 string 类型变量, 所以去掉了const
	// 如果加上 const,两种初始化方式都可以
};

template <typename T>
Adg<T>::Adg(std::string& name, const T& value) : _name(name), _value(value) {
    
     }
//上一条款提到了成员变量是const 或者 reference, 他们就一定需要初值,不能被赋值。
//也就是不能写成下面这样
/*
template <typename T>
Adg<T>::Adg(std::string& name, const T& value){ 
 _name = name;
 _value = value;
}
*/
int main() {
    
    
	std::string newDog("gwww");
	Adg<int> no1(newDog, 2);
	Adg<int> no2(no1);					// 正确,调用 copy 构造函数
	no2 = no1;							// 错误! 
	return 0;
}

从上面代码可以得出,当 no1._name 指向string对象 no1 时,不能通过 copy assignment 操作符改变 no1._name 所指的对象来指向 no2。不过调用 copy 构造函数不会出现这种情况。
当然,更改 const 成员也是不合法的。

  • 最后请记住:
    编译器可以暗自为 class 创建 default 构造函数、copy 构造函数、copy assignment 操作符,以及析构函数( 如果它们被调用的话)。

猜你喜欢

转载自blog.csdn.net/weixin_48033173/article/details/108938391