拷贝构造函数和赋值运算符

在默认情况下(用户没有定义,但是也没有显式的删除),编译器会自动的隐式生成一个拷贝构造函数和赋值运算符。但用户可以使用delete来指定不生成拷贝构造函数和赋值运算符,这样的对象就不能通过值传递,也不能进行赋值运算

class Person
{
public:
    Person(const Person& p) = delete;
    Person& operator=(const Person& p) = delete;
private:
    int age;
    string name;
};

上面的定义的类Person显式的删除了拷贝构造函数和赋值运算符,在需要调用拷贝构造函数或者赋值运算符的地方,会提示_无法调用该函数,它是已删除的函数_。

还有一点需要注意的是,拷贝构造函数必须以引用的方式传递参数。这是因为,在值传递的方式传递给一个函数的时候,会调用拷贝构造函数生成函数的实参。如果拷贝构造函数的参数仍然是以值的方式,就会无限循环的调用下去,直到函数的栈溢出。

何时调用

拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象;但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而赋值运算符是将对象的值复制给一个已经存在的实例。这种区别从两者的名字也可以很轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生。如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符。

调用拷贝构造函数主要有以下场景:

  • 对象作为函数的参数,以值传递的方式传给函数。
  • 对象作为函数的返回值,以值的方式从函数返回;返回时,又调用了一次赋值构造函数,相当于又定义一个对象,然后把值赋值给最后这个赋值构造函数,也就是临时对象。
  • 使用一个对象给另一个对象初始化

代码如下:

#include <iostream>
#include <fstream>

using namespace std;
class Person
{
public:
	///F 默认构造函数
	Person() 
	{
		cout << "moren Constructor" << endl;
	}

	///F 赋值构造函数
	Person(const Person& p)
	{
		
		
		cout<< "Copy Constructor" << endl;
	}
	///赋值运算符
	Person& operator=(const Person& p)
	{
		cout << "Assign" << endl;
		return *this;
	}

private:
	int age;
	char name;
};

void f(Person p)
{
	return;
}

Person f1()
{
	Person p;
	return p;
}
int main()
{
	Person p;		///F 默认构造函数
	Person p1 = p;    /// 1拷贝构造函数
	Person p2;
    // 2	赋值运算
	p2 = p;    
    // 3	//(****赋值构造函数**** 先是赋值构造函数,然后调用函数f    
	f(p2);         


   // 4	///xxxxx 错误 赋值构造函数****  
 //这里先调用f1()函数,然后里面是默认构造函数,返回时赋值构造函数
	p2 = f1();      
 // 5	赋值构造函数
	Person p3 = f1(); 
	getchar();
	return 0;
}

分析如下:(对上面解释)

  1. 这是虽然使用了"=",但是实际上使用对象p来创建一个新的对象p1。也就是产生了新的对象,所以调用的是拷贝构造函数。
  2. 首先声明一个对象p2,然后使用赋值运算符"=",将p的值复制给p2,显然是调用赋值运算符,为一个已经存在的对象赋值。
  3. 以值传递的方式将对象p2传入函数f内,调用拷贝构造函数构建一个函数f可用的实参.先是赋值构造函数,然后调用函数f
  4. 这条语句拷贝构造函数和赋值运算符都调用了。函数f1以值的方式返回一个Person对象,在返回时会调用拷贝构造函数创建一个临时对象tmp作为返回值;返回后调用赋值运算符将临时对象tmp赋值给p2.
  5. 按照4的解释,应该是首先调用拷贝构造函数创建临时对象;然后再调用拷贝构造函数使用刚才创建的临时对象创建新的对象p3,也就是会调用两次拷贝构造函数。不过,编译器也没有那么傻,应该是直接调用拷贝构造函数使用返回值创建了对象p3。

参考:

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

帅气滴点C

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值