本文前面主要介绍了拷贝构造函数和赋值运算符函数的区别,以及在什么时候调用拷贝构造函数、什么情况下调用赋值运算符函数。最后,分析了下深拷贝和浅拷贝的问题,即拷贝构造函数和赋值运算符函数的必要性和意义。本文综合了《C++ 拷贝构造函数和赋值运算符》和《拷贝构造函数和赋值函数的必要性和意义》的内容,并加上自己的理解。
C++ 拷贝构造函数和赋值运算符函数
本文主要介绍了拷贝构造函数和赋值运算符函数的区别,以及在什么时候调用拷贝构造函数、什么情况下调用赋值运算符函数。最后,简单的分析了下深拷贝和浅拷贝的问题。
拷贝构造函数和赋值运算符
在默认情况下(用户没有定义,但是也没有显式的删除),编译器会自动的隐式生成一个拷贝构造函数和赋值运算符函数(缺省的)。
class Person
{
public:
...
Person(const Person& p) = delete;
Person& operator=(const Person& p) = delete;
private:
int age;
string name;
};
用户可以使用delete来指定不生成拷贝构造函数和赋值运算符,这样的对象就不能通过值传递,也不能进行赋值运算。上面的定义的类 Person 显式地删除了拷贝构造函数和赋值运算符,在需要调用拷贝构造函数或者赋值运算符的地方,会提示无法调用该函数,它是已删除的函数。
如果我们不想编写拷贝构造函数和赋值运算符函数,又不允许别人使用编译器隐式生成的缺省函数,同时也不想显式地删除拷贝构造函数和赋值运算符函数,我们还可以通过将拷贝构造函数和赋值运算符函数声明成类私有函数的方式来实现。如下所示:
class Person
{
public:
...
private:
Person(const Person& p); //以常量引用的方式传递参数
Person& operator=(const Person& p);//返回值类型为该类型的引用
int age;
string name;
};
还有两点需要注意的是:
- 拷贝构造函数必须以引用的方式传递参数,基本上都是传常量引用的方式传递函数参数。这是因为,在值传递的方式传递给一个函数的时候,会调用拷贝构造函数生成函数的实参。如果拷贝构造函数的参数仍然是以值的方式,就会无限循环的调用下去,直到函数的栈溢出。
- 赋值运算符函数的返回值类型要声明为该类型的引用,并在函数结束前返回实例自身的的引用(*this)