(转自: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
分享到:
相关推荐
引用传递结合了值传递的安全性和指针传递的效率,是C++中推荐使用的参数传递方式之一。对于小型数据类型,如基本类型和小的类对象,引用传递和值传递之间的性能差异可能不明显,但对于大型数据结构,引用传递可以...
- **效率更高**:当处理大型对象时,使用引用传递可以避免复制整个对象的成本,从而提高程序的运行效率。 #### 使用引用传递的注意事项 虽然引用传递具有很多优点,但在使用时也需要注意以下几点: - **必须初始...
通过引用传递参数,函数内部直接操作实参,节省了复制数据的时间和空间,提高了效率。 常引用(Const Reference)是另一种形式的引用,它通过在引用声明前加上`const`关键字,如`const int &ra = a;`。常引用不能...
在C++中,有两种主要的数据传递方式:按值传递(by value)和按引用传递(by reference)。当传递类对象时,通常推荐使用按引用传递,因为类对象往往较大,按值传递可能导致大量的内存复制,效率较低。 1. 按值传递...
因此,即使在函数参数中使用按值传递,也不会导致原始字符串的改变。C#中字符串通常按引用传递,因为即使它是按值传递的,也只会传递对字符串对象的引用,而不是字符串内容的副本。 ```csharp public void ...
通过上述分析可以看出,C++中的参数传递机制有三种:值传递、指针传递和引用传递。每种方式都有其特点和适用场景: - **值传递**:适合于不需要修改原始数据的情况,尤其是对于内置类型或较小的对象。 - **指针传递...
C和C++中的函数参数传递方式主要分为值传递、指针传递和引用传递。这些方式决定了参数在函数调用时的传值行为,以及它们在函数执行后是否能够影响原始数据。下面详细解释这些传递方式的知识点。 1. 值传递(Call by...
与传值调用相比,这种方式避免了复制整个对象,从而提高了效率。 ### 结论 通过本文的介绍,我们可以了解到C++中函数参数的不同传递方式及其特点。传值调用、传地址调用和传引用调用各有优缺点,适用于不同的场景...
在编程语言中,值传递和引用传递是函数参数传递的两种基本方式,它们涉及到内存管理、数据安全以及程序效率等多个重要方面。这篇文章将深入探讨这两种传递方式,并通过内存解析来帮助理解它们的工作原理。 首先,...
引用经常被用作函数参数,以实现高效的值传递。这可以避免复制大量数据带来的开销,尤其是在传递大型数据结构时。 **示例**: ```cpp void swap(int &p1, int &p2) { int temp = p1; p1 = p2; p2 = temp; } ```...
总结起来,C++中的指针和引用都是为了提高程序的灵活性和效率,它们各自具有独特的应用场景和使用规则。理解并熟练掌握这两种工具,对于编写高效、安全的C++代码至关重要。通过实际编程练习和分析,我们可以更好地...
在C++编程语言中,引用(Reference)是一个非常重要的特性,它为程序员提供了另一种方式来访问和操作已存在的变量。引用不同于指针,它更像是一个变量的别名,一旦引用被初始化指向某个变量,就不能再改变引用的目标...
- **可变参数传递**:与C中的值传递不同,C++的引用参数允许函数修改实参的值。在`swapint`函数的例子中,通过引用,函数可以直接修改传入的`a`和`b`的值,而不需要借助临时变量或指针。 - **效率提升**:对于大型...
例如,使用引用传递代替值传递可以减少不必要的对象构造,而当需要返回一个临时对象时,如果返回对象过大,应当优先考虑移动语义(Move Semantics)以减少不必要的资源开销。 本书还深入讨论了C++中的一些高级特性...
// 然后可以在QML中使用这些路径,例如赋值给Image组件的source属性 } } ``` 这个过程展示了C++和QML之间的强大协作,使得我们可以充分利用两者的优点:C++处理复杂的逻辑和数据管理,而QML负责创建直观、动态的...
以前的C语言中函数参数传递是值传递,如果有大块数据作为参数传递的时候,采用的方案往往是指针,因为这样可以避免将整块数据全部压栈,可以提高程序的效率。但是现在(C++中)又增加了一种同样有效率的选择(在某些...
以前的 C 语言中函数参数传递是值传递,如果有大块数据作为参数传递的时候,采用的方案往往是指针,因为这样可以避免将整块数据全部压栈,可以提高程序的效率。但是现在(C++中)又增加了一种同样有效率的选择(在...
- **引用**主要用来作为函数参数,提高函数调用效率。由于引用不占用额外的存储空间,也不需要复制数据,因此使用引用传递大对象时可以避免不必要的性能开销。另外,引用常用于表示不可更改的变量,以增加代码的...