C++拷贝构造函数的一点收获


     看了《C++编程思想》的拷贝构造函数部分,反反复复看了几遍终于想通是怎么回事了,现在做个记录。


    前提1:对于没有定义拷贝构造函数的类,编译器会为其创建一个默认的拷贝构造函数,只不过是最简单的位拷贝。

    前提2:在执行函数的时候,先将函数参数压栈,再将返回地址压栈,然后再执行函数代码,产生局部变量,如下图。在函数最后,先把返回值赋给返回地址的变量,然后函数结束,销毁在函数中产生的局部变量。

     

    前提3:编译器为个正确地计算一个表达式而需要一个临时对象时,编译器可以创建一个,但临时对象的存在时间应尽可能的短。

   

    先看第一个例子

#include <fstream>
#include <string>

using namespace std;
ofstream out( "HowMany.txt" );

class HowMany
{
	static int objectCount;
public:
	HowMany(){ objectCount++; }
	static void print( const string &msg = "" )
	{
		if ( msg.size() !=0 )
			out<<msg<<": ";
		out<<"objectCount = "<<objectCount<<endl;
	}
	~HowMany()
	{
		objectCount--;
		print( "~HowMany()" );
	}
};

int HowMany::objectCount = 0;

HowMany f( HowMany x )
{
	x.print( "x argument inside f()" );
	return x;
}

int main()
{
	HowMany h;
	HowMany::print( "after construction of h" );
	HowMany h2 = f( h );
	HowMany::print( "after print f()" );
}

    输出文件中为:

	after construction of h: objectCount = 1
	x argument inside f(): objectCount = 1
	~HowMany(): objectCount = 0
	after print f(): objectCount = 0
	~HowMany(): objectCount = -1
	~HowMany(): objectCount = -2

    直接看main函数

12行不解释了,其对应的输出为:

	after construction of h: objectCount = 1

        此时在内存中存在一个HowMany对象h

3行

    根据前提2,先将参数和h2的地址(返回地址)压栈,由于函数f的参数是按值传递的,将h传递时调用拷贝构造函数(是默认的拷贝构造函数,前提1),拷贝给x,因为是位拷贝,所以objectCount并没有改变,输出为

	x argument inside f(): objectCount = 1

        内存中的对象:hx

    函数结束,根据前提2x拷贝给h2,销毁局部变量x(析构函数,objectCount-1),输出为:

	~HowMany(): objectCount = 0

        内存中:hh2

4行也不解释了,输出为:

	after print f(): objectCount = 0

        内存中:hh2

最后程序结束,销毁内存中的hh2(析构函数,objectCount--,先销毁h2),输出为:

	~HowMany(): objectCount = -1
	~HowMany(): objectCount = -2


    以上是没有定义拷贝构造函数的情况,再来看一个定义了构造函数的例子

#include <fstream>
#include <string>

using namespace std;
ofstream out( "HowMany.txt" );

class HowMany2
{
	string name;
	static int objectCount;
public:
	HowMany2( const string &id = "" ) : name( id )
	{ 
		objectCount++;
		print( "HowMany2" );
	}
	~HowMany2()
	{
		objectCount--;
		print( "~HowMany2()" );
	}
	HowMany2( const HowMany2 &p ) : name( p.name )
	{
		name += " copy";
		++objectCount;
		print( "HowMany2(const HowMany2 &)" );
	}
	void print( const string &msg = "" ) const
	{
		if ( msg.size() !=0 )
			out<<msg<<endl;
		out<<"\t"<<name<<": "<<"objectCount="<<objectCount<<endl;
	}

};

int HowMany2::objectCount = 0;

HowMany2 f( HowMany2 x )
{
	x.print( "x argument inside f()" );
	out<<"Returning from f()"<<endl;
	return x;
}

int main()
{
	HowMany2 h( "h" );
	out<<"Entering f()"<<endl;
	HowMany2 h2 = f( h );
	h2.print( "h2 after call to f()" );
	out<<"Call f(),no return value"<<endl;
	f( h );
	out<<"After call to f()"<<endl;
}

输出文件中为:

	HowMany2
		h: objectCount=1
	Entering f()
	HowMany2(const HowMany2 &)
		h copy: objectCount=2
	x argument inside f()
		h copy: objectCount=2
	Returning from f()
	HowMany2(const HowMany2 &)
		h copy copy: objectCount=3
	~HowMany2()
		h copy: objectCount=2
	h2 after call to f()
		h copy copy: objectCount=2
	Call f(),no return value
	HowMany2(const HowMany2 &)
		h copy: objectCount=3
	x argument inside f()
		h copy: objectCount=3
	Returning from f()
	HowMany2(const HowMany2 &)
		h copy copy: objectCount=4
	~HowMany2()
		h copy: objectCount=3
	~HowMany2()
		h copy copy: objectCount=2
	After call to f()
	~HowMany2()
		h copy copy: objectCount=1
	~HowMany2()
		h: objectCount=0

    看main函数

    12行不解释,输出为:

	HowMany2
		h: objectCount=1
	Entering f()


        内存中:h

3行,同样先将参数和返回地址压栈。由于HowMany2定义了自己的拷贝构造函数,调用该拷贝构造函数将h拷贝给局部变量xobjectCount++),然后执行函数,输出为:

	HowMany2(const HowMany2 &)
		h copy: objectCount=2
	x argument inside f()
		h copy: objectCount=2
	Returning from f()

        内存中:hx

    在函数最后,与第一个例子一样,将x拷贝给h2(objectCount++),销毁xobjectCount--),输出为:

	HowMany2(const HowMany2 &)
		h copy copy: objectCount=3
	~HowMany2()
		h copy: objectCount=2

        内存中:hh2

45行输出为:

	h2 after call to f()
		h copy copy: objectCount=2
	Call f(),no return value

        内存中:hh2

6行,函数结束之前与第3行一样,输出为:

	HowMany2(const HowMany2 &)
		h copy: objectCount=3
	x argument inside f()
		h copy: objectCount=3
	Returning from f()

        内存中:hh2x

    在函数的最后,将x拷贝给返回值,根据前提三,会创建一个临时变量,就叫他n吧,x拷贝给n(objectCount++),销毁x(objectCount--),输出为:

	HowMany2(const HowMany2 &)
		h copy copy: objectCount=4
	~HowMany2()
		h copy: objectCount=3

        内存中:hh2n

    因为临时变量n的存在时间应尽可能的短,所以紧接着销毁n(析构objectCount--),输出为:

	~HowMany2()
		h copy copy: objectCount=2

        内存中:hh2

7行,输出为:

	After call to f()


        内存中:hh2

程序结束,销毁hh2(先销毁h2),输出为:

	~HowMany2()
		h copy copy: objectCount=1
	~HowMany2()
		h: objectCount=0

    终于解释完了,最后做一个总结,借用《C++编程思想》里的一句话:“拷贝构造函数实现了按值传递方式的参数传递和返回”。

      







































评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值