由Point p1 = p和p1 = p的区别想到的关于copy构造函数和赋值操作符重载函数的调用时机问题...

本文通过示例程序详细解释了C++中拷贝构造函数与赋值操作符重载函数的调用时机及区别。指出在对象声明同时进行初始化时调用拷贝构造函数,在已有对象间进行赋值时调用赋值操作符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天在论坛上看到一个帖子:http://bbs.youkuaiyun.com/topics/390642928?page=1#post-396087799,涉及到一个copy构造函数和赋值操作符重载函数的调用时机问题,更正了我一直以来的一个对着俩函数的理解上的误区,这个错误相信很多人都会犯过,随后我问了周围几个人,果然不出所料!特此记录,以飨读者!

首先看这样一个简单的程序,涉及到copy构造函数和赋值操作符重载:

#include<iostream>

using namespace std;

class Point 
{ 
private: 
	int m_x,m_y; 
public: 
	Point() 
	{ 
		m_x = 0; 
		m_y = 0; 
	} 
	Point(int x, int y) 
	{ 
		m_x = x; 
		m_y = y; 
	} 
	Point(const Point& p)
	{
		m_x = p.m_x;
		m_y = p.m_y;
		cout<<"copy constructor is called!"<<endl;
	}
	Point& operator=(const Point& p)
	{
		m_x = p.m_x;
		m_y = p.m_y;
		cout<<"= operator is called!"<<endl;

		return *this;
	}
}; 

int main()
{
	Point p(1, 2);
	Point p1 = p;

	return 0;
}

在main函数中的Point p1 = p这条语句,程序的执行结果应该是调用哪个函数呢?看下运行结果:

令人惊讶的是,调用的是copy构造函数,并没有像预期的那样调用赋值操作符重载函数!

百思不得其解,将程序做了下改动:

#include<iostream>

using namespace std;

class Point 
{ 
private: 
	int m_x,m_y; 
public: 
	Point() 
	{ 
		m_x = 0; 
		m_y = 0; 
	} 
	Point(int x, int y) 
	{ 
		m_x = x; 
		m_y = y; 
	} 
	Point(const Point& p)
	{
		m_x = p.m_x;
		m_y = p.m_y;
		cout<<"copy constructor is called!"<<endl;
	}
	Point& operator=(const Point& p)
	{
		m_x = p.m_x;
		m_y = p.m_y;
		cout<<"= operator is called!"<<endl;

		return *this;
	}
}; 

int main()
{
	Point p(1, 2);
	Point p1;
	p1 = p;

	return 0;
}

将Point p1 = p;改成了Point p1; p1 = p;看下执行结果:


这次调用的确实赋值操作符的重载函数!非常奇怪!

在度娘的帮助下,终于找到了答案!其中的关键就是

Point p1 = p;

Point p1;

p1 = p;

的区别问题!

其实Point p1 = p与Point p1(p)是等价的,都表示“用实例p来初始化p1”,调用的当然是copy构造函数了,Point p1 = p千万不能理解成是把p赋值给p1,这是我一直以来犯下的一个错误!


Point p1;

p1 = p;

就表示先定义并初始化一个Point实例p1,然后将p赋值给p1,这当然会调用=operator了!到这里终于恍然大悟了!

总结了一下copy构造函数和赋值运算法重载函数的调用时机:

1、对象在创建时使用其他的对象初始化

Point p(q); //此时复制构造函数被用来创建实例p
Point p = q; //此时复制构造函数被用来在定义实例p时初始化p

2、对象作为函数的参数进行值传递时

func(p); //此时p作为函数的参数进行值传递,p入栈时会调用复制构造函数创建一个局部对象,与函数内的局部变量具有相同的作用域.


3、一个对象以值传递的方式从函数返回

Point func()

{

Point p;

return p;

}


需要注意的是,赋值并不会调用复制构造函数,赋值只是赋值运算符(重载)在起作用
p = q; //此时没有复制构造函数的调用!

简单来记的话就是,如果对象在声明的同时将另一个已存在的对象赋给它,就会调用复制构造函数;如果对象已经存在,然后将另一个已存在的对象赋给它,调用的就是赋值运算符(重载)
















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值