(转自:http://www.diybl.com/course/3_program/c++/cppjs/2008215/99861.html)
我们写一个函数,比如 objclass fun(objclass obj); objclass是类名,obj是对象,fun是函数名。
然后调用此函数,编译器分两个步骤:
1.每次通过值传递的方式给函数传递一个对象时,都会建立一个该对象的拷贝。
2.每次通过值从函数返回一个对象时,也会建立另一个拷贝。
也就是说调用一次此函数,系统会自动建立两次的对象拷贝,然后再调用两次析构函数释放对象的拷贝。
我们知道当调用函数的时候,这些对象被复制到栈中,这样做会费时且占用内存,当使用用户定义的大对象时,这种拷贝带来的内存开销是非常显著的。当时用用户建立的类时,每次生成这种临时的拷贝都要调用一个特殊的构造函数:复制构造函数。当函数返回时,对象的临时拷贝被删除,此时需要调用对象的析构函数。如果返回对象时通过值传递的方式,那么必须建立对象的拷贝,然后再删除。对于很大的对象,调用构造函数和析构函数在速度和内存方面都会造成很大的开销。
为了说明这一点见下面的例子:
#include <cstdlib>
#include <iostream>
using namespace std;
class class_A
{
public:
class_A()
{
cout<<"class_A 构造函数..."<<endl;
}
class_A(class_A &)
{
cout<<"class_A 复制构造函数..."<<endl;
}
~class_A()
{
cout<<"class_A 析构函数..."<<endl;
}
};
//-------------------------------------------------------------------------------------------
class_A funOne(class_A obj);
class_A *funTwo(class_A *obj);
class_A funOne(class_A obj)
{
cout<<"函数funOne返回..."<<endl;
return obj;
}
class_A *funTwo(class_A *obj)
{
cout<<"函数funTwo返回..."<<endl;
return obj;
}
//-------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
//调用 class_A的构造函数
class_A abc;
//-------------------------------------------------------------------------------------------
cout<<"调用函数funOne..."<<endl;
//1.采用值传递的方式传递 class_A类的对象,因此在栈中会建立一个对象的拷贝,作为
//被调用函数的局部对象,这样就调用了复制构造函数。
//2.当函数返回的时候,函数采取值传递的方式返回 class_A类的对象,这样又会建立对象
//的另一个拷贝,再次调用复制构造函数。
funOne(abc);
//1.funOne()返回值不赋给任何对象,因此这个返回的临时值就被丢弃了,这时调用析构函数。
//2.funOne()结束之后,因此它的局部拷贝的作用域也随之结束和被删除,这时又一次调用了
//析构函数。
//-------------------------------------------------------------------------------------------
cout<<"调用函数funTwo..."<<endl;
//传递参数采用引用的方式,因此,没有对象进行拷贝,也就没有输出。
funTwo(&abc);
//返回 class_A类的对象,由于这一次依然采用引用传递的方式,因此还是没有调用构造函数和析构函数。
//-------------------------------------------------------------------------------------------
system("PAUSE");
return EXIT_SUCCESS;
}
以上code可以直接复制使用~~
文章出处:飞诺网(www.diybl.com):http://www.diybl.com/course/3_program/c++/cppjs/2008215/99861.html