现在的位置: 首页 > 综合 > 正文

聊聊C++中复制构造函数和赋值操作符

2013年09月11日 ⁄ 综合 ⁄ 共 2304字 ⁄ 字号 评论关闭

复制构造函数:只有单个形参,而且形参是对本类类型对象的引用(常用const修饰),这样的构造函数称为复制构造函数。与默认构造函数一样,复制构造函数可由编译器隐式调用。复制构造函数可以用于:

  • 根据另一个同类型的对象显式或隐式初始化一个对象
  • 复制一个对象,将它作为实参传给一个函数
  • 从函数返回时复制一个对象
  • 初始化顺序容器中的元素
  • 根据元素初始化列表初始化数组元素

赋值操作符:与复制构造函数一样,如果没有定义自己的赋值操作符,则编译器会合成一个。

下面我写了一个程序对以上描述做出解释。

#include<iostream>
#include<string>
#include<vector>
using namespace std;
class Test
{
public:
	Test(){str="Kevin";x=10;cout<<"default constructor"<<endl;}				//construction function
	Test(const Test& t){str=t.str;x=t.x; cout<<"copy construction was used!"<<endl;}	//copy constructor 
	Test& operator=(const Test& t){str=t.str;x=t.x;cout<<"operator="<<endl;return *this;}	
private:												
	string str;
	int x;
};
Test f(Test t)
{
	cout<<"f function"<<endl;
	return t;
}
main()
{
	cout<<"Test t:"<<endl;
	Test t;

	cout<<endl<<"vector<Test> vec1(5):"<<endl;
	vector<Test> vec1(5);

	cout<<endl<<"vector<Test> vec2(5,t):"<<endl;
	vector<Test> vec2(5,t);

	cout<<endl<<"Test te[5]:"<<endl;
	Test te[5];

	cout<<endl<<"Test t2(t):"<<endl;
	Test t2(t);

	cout<<endl<<"f(t2):"<<endl;
	f(t2);

	cout<<endl<<""<<endl;
	Test* p1=new Test();
	*p1=t;
	Test* p2=&t;
	Test t3=t;
	Test t4;
	t4=t;
}

以上程序的输出结果是:

default constructor

vector<Test> vec1(5):
default constructor
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!

vector<Test> vec2(5,t):
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!
copy construction was used!

Test te[5]:
default constructor
default constructor
default constructor
default constructor
default constructor

Test t2(t):
copy construction was used!

f(t2):
copy construction was used!
f function
copy construction was used!


default constructor
operator=
copy construction was used!
default constructor
operator=

     由上面程序中的第26行可以看出,复制构造函数被用于初始化容器元素的时候,如果没有之处元素的初始值,则编译器会首先调用默认的构造函数创建一个临时制,然后使用复制构造函数将临时制复制到每一个元素中。当指明了元素的初始值(如29行所示)时,编译器会直接将其复制到每一个元素。

     由程序中第32行的运行结果可以看出,定义一个类类型的数组时,编译器会利用类的默认构造函数初始化每一个元素。

由程序中第38行的运行结果可以看出,当类类型被用做形参与返回值时,各自发生了一次复制。C++ primer中这样描述:“当函数的形参为非引用类型的时候,将复制实参的值。类似的,以非引用类型做返回值时,将返回return语句中的值的副本”。按照我的理解就是“当形参和返回值都不是引用时,进入函数时发生一次复制,离开函数时发生一次复制”。

     程序的第41行至第46行是为了说明复制构造函数与赋值操作符的区别设计的。我们可以看到*p1=t;这一句用到了赋值操作符,t4=t;这一句也用到了赋值操作符,其他各种形式的语句都用的是复制构造函数。从中可以总结出一句话“从无到有是copy,从有到有是赋值”。这句话怎么理解呢?大家看,*p1=t这一句中的*p是早已经声明了的,在*p1声明的时候已经完成了它的初始化。在*p1=t这句中*p是已经初始化过的,所以这里*p1=t应用的是赋值操作符。同理第46行的中的t4也是一个已经声明过,完成了初始化的变量,所以在语句t4=t中使用的也是赋值操作符。而在Test t3=t;
 这样的语句中,t3是刚刚声明出来的,还没有初始化,要求编译器按照t的内容初始化t3。这正好是复制构造函数的作用。

抱歉!评论已关闭.