13.1拷贝、赋值与销毁
When we define a class, we specify—explicitly or implicitly—what happens when objects of that class type are copied, moved, assigned, and destroyed. A class controls these operations by defining five special member functions:
copy constructor, copyassignment operator, move constructor, move-assignment operator, and destructor.
The copy and move constructors define what happens when an object is initialized from another object of the same type. The copy- and move-assignment operators define what happens when we assign an object of a class type to another object of that same class type.Collectively, we’ll refer to these operations as copy control.
如果一个构造函数的第一个参数是自身类类型的引用,且任何额外参数都有默认值,则此构造函数是拷贝构造函数:
(练习13.1)
class Foo {
public:
Foo(); // default constructor
Foo(const Foo&); // copy constructor
// ...
};
如果我们没有为一个类定义拷贝构造函数,编译器会为我们定义一个。
作为一个例子,我们的Sales_data类的合成拷贝构造函数等价于:
class Sales_data {
public:
// other members and constructors as before
// declaration equivalent to the synthesized copy constructor
//与合成的拷贝构造函数等价的拷贝构造函数声明
Sales_data(const Sales_data&);
private:
std::string bookNo;
int units_sold = 0;
double revenue = 0.0;
};
// equivalent to the copy constructor that would be synthesized for Sales_data
//与Sales_data的合成的拷贝构造函数等价
Sales_data::Sales_data(const Sales_data &orig) :
bookNo(orig.bookNo), // uses the string copy constructor
units_sold(orig.units_sold), // copies orig.units_sold
revenue(orig.revenue) // copies orig.revenue
{ } //空函数体
string dots(10, '.'); // direct initialization
string s(dots); // direct initialization
string s2 = dots; // copy initialization
string null_book = "9-999-99999-9"; // copy initialization
string nines = string(100, '9'); // copy initialization
拷贝初始化时,编译器将右侧运算对象拷贝到正在创建的对象中。
拷贝初始化是依靠拷贝构造函数或移动构造函数来完成的。
练习13.5:
class HasPtr
{
public:
HasPtr(const std::string& s = std::string()) : ps(new std::string(s)), i(0){}
HasPtr(const HasPtr& hp) : ps(new std::string(*hp.ps)), i(hp.i) {}
private:
std::string* ps;
int i;
};
重载运算符本质上是函数。赋值运算符就是一个名为 operator= 的函数。
赋值运算符通常应该返回一个指向其左侧运算对象的引用。
三/五法则:
三个基本操作可以控制类的拷贝操作:拷贝构造函数、拷贝赋值运算符、析构函数。