用值和用地址传递对象
程序员文章站
2022-07-14 18:24:36
...
[size=medium]今天学习《从新手到高手C++全部精华教程》,http://www.iteye.com/topic/1126275
“传值和传地址的区别是,传值由于是传递的原始变量的副本,因此不会改变原始变量的值,而传地址则可以改变原始变量的值。假如仅仅是传递变量的话,采用指针或引用这种传地址的方式的优势并不明显,但是如果传递的是较大的对象的话,那么传地址的优势是十分明显的。这时因为,在用传值的方式传递一个对象时,会像传变量一样建立一个该对象的拷贝,而从函数返回一个对象时,也要建立这个返回的对象的一个拷贝。但是若对象的数据很大时,这种内存的开销是相当可观的。然而,按值传递的开销远不如此,由于在传递对象的过程中需要复制对象,因此会默认调用复制构造函数,该函数就是要创建该对象的副本。同时,若返回的仍是该对象,那么仍按照传值的方式,就又会调用复制构造函数创建该对象的临时副本,当该值成功返回调用程序后,在调用该对象的析构函数删除临时拷贝并释放内存。”
举例如下:[/size]
[size=medium]按值传递对象,如上图所示,结果如下[/size]
[img]http://dl.iteye.com/upload/attachment/0076/4393/08cd61b9-a890-39e3-94ab-108f24ba2967.jpg[/img]
[size=medium]按地址传递:
按地址传递对象:[/size]
结果如下:
[img]http://dl.iteye.com/upload/attachment/0076/4395/9ff9957d-f076-36fa-8463-b23f5f1eafab.jpg[/img]
[size=medium]若func函数返回的不是对象,而是指向该对象的指针,则如下:[/size]
[size=medium]结果如下:[/size]
[img]http://dl.iteye.com/upload/attachment/0076/4397/7d17b193-28cf-3d4c-8136-395090049744.jpg[/img]
“传值和传地址的区别是,传值由于是传递的原始变量的副本,因此不会改变原始变量的值,而传地址则可以改变原始变量的值。假如仅仅是传递变量的话,采用指针或引用这种传地址的方式的优势并不明显,但是如果传递的是较大的对象的话,那么传地址的优势是十分明显的。这时因为,在用传值的方式传递一个对象时,会像传变量一样建立一个该对象的拷贝,而从函数返回一个对象时,也要建立这个返回的对象的一个拷贝。但是若对象的数据很大时,这种内存的开销是相当可观的。然而,按值传递的开销远不如此,由于在传递对象的过程中需要复制对象,因此会默认调用复制构造函数,该函数就是要创建该对象的副本。同时,若返回的仍是该对象,那么仍按照传值的方式,就又会调用复制构造函数创建该对象的临时副本,当该值成功返回调用程序后,在调用该对象的析构函数删除临时拷贝并释放内存。”
举例如下:[/size]
#include<iostream>
using namespace std;
class A{
public:
A(){cout<<"执行构造函数创建一个对象"<<endl;}
A(A&){cout<<"执行复制构造函数创建该对象的副本"<<endl;}
~A(){cout<<"执行析构函数删除该对象"<<endl;}
};
A func(A one){
return one;
}
int main(){
A a;
func(a);
return 0;
}
[size=medium]按值传递对象,如上图所示,结果如下[/size]
[img]http://dl.iteye.com/upload/attachment/0076/4393/08cd61b9-a890-39e3-94ab-108f24ba2967.jpg[/img]
[size=medium]按地址传递:
按地址传递对象:[/size]
#include<iostream>
using namespace std;
class A{
public:
A(){cout<<"执行构造函数创建一个对象"<<endl;}
A(A&){cout<<"执行复制构造函数创建该对象的副本"<<endl;}
~A(){cout<<"执行析构函数删除该对象"<<endl;}
};
A func(A *one){
return *one; //如果是return one;的话,则是错误的,因为one是指针,而函数func的返回类型是对象
}
int main(){
A a;
func(&a);
return 0;
}
结果如下:
[img]http://dl.iteye.com/upload/attachment/0076/4395/9ff9957d-f076-36fa-8463-b23f5f1eafab.jpg[/img]
[size=medium]若func函数返回的不是对象,而是指向该对象的指针,则如下:[/size]
#include<iostream>
using namespace std;
class A{
public:
A(){cout<<"执行构造函数创建一个对象"<<endl;}
A(A&){cout<<"执行复制构造函数创建该对象的副本"<<endl;}
~A(){cout<<"执行析构函数删除该对象"<<endl;}
};
A* func(A *one){ //将func函数的返回类型改为指针后,在调用该函数的时候就不用再次调用构造函数了
return one; //同时,函数的返回值必须也是指针才可以
}
int main(){
A a;
func(&a); //按地址传递,则实参必须是地址,所以用&a,同时,形参必须要接收地址,所以是*one
return 0;
}
[size=medium]结果如下:[/size]
[img]http://dl.iteye.com/upload/attachment/0076/4397/7d17b193-28cf-3d4c-8136-395090049744.jpg[/img]