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

        今天在论坛上看到一个帖子:http://bbs.csdn.net/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这条语句,程序的执行结果应该是调用哪个函数呢?看下运行结果:

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

        令人惊讶的是,调用的是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和p1 = p的区别想到的关于copy构造函数和赋值操作符重载函数的调用时机问题_第2张图片

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

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

               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; //此时没有复制构造函数的调用!

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
















你可能感兴趣的:(copy构造函数,赋值运算符重载)