今天在论坛上看到一个帖子: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; }
令人惊讶的是,调用的是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(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; //此时没有复制构造函数的调用!
简单来记的话就是,如果对象在声明的同时将另一个已存在的对象赋给它,就会调用复制构造函数;如果对象已经存在,然后将另一个已存在的对象赋给它,调用的就是赋值运算符(重载)