C++按值和按址传递对象的思考和优化

C++是一门面向对象(OOP)编程语言,在这门语言中也有函数,函数的参数可以是变量数值,当然也可以是对象。所以,传统地就有关于对象是按值传递还是按址传递的讨论。

在C语言中,按值传递在很多情况下可以出色地完成任务,而且也很好理解,但是在C++中,因为有了类的对象这个可能的庞然大物(指他的数据特别大),如果还用传值的方式进行的话,会很浪费内存空间。本文就具体讨论这个问题。

在C++中,将一个对象按值传递时,会默认调用一个复制构造函数做一个这个参数的副本给函数。默认的复制构造函数名字是:类名(类名&)。请看下面代码:

#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 (void)
{
    A a;
    func(a);

    return 0;
}


这里的执行结果是:


这里我们发现执行了一次构造函数,两次复制构造函数,三次析构函数,结果很有意思,现在分析如下:

第一次只执行构造函数是因为新建了A类的对象a,因此调用构造函数来构造对象,当main函数调用func函数的时候,将对象a的值传给了func函数,这个时候就要调用复制构造函数来做一个对象a的副本,当func函数执行完毕时,要将对象one返回,这个时候还要调用复制构造函数来做一个one对象的副本,然后调用析构函数释放func函数中的对象one,当回到main函数中的时候,由于返回的one对象没有使用,所以这个时候又要调用析构函数来释放这个返回的对象,当main函数执行完毕时,a对象的也该释放了,这个时候就要调用类的析构函数来释放a对象的空间。从上面的分析中我们看出这个过程中,有很多次调用,每次调用都要进行对象的复制,既浪费了内存,有降低了程序的执行效率。该怎么优化呢?这个时候我们可以使用传址的方式来进行,将代码修改如下:

#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 (void)
{
    A a;
    func(&a);

    return 0;
}

可以看到这里将传参的方式修改成了按址的方式,他的执行结果如下:


这里减少了一次复制构造函数和析构函数的调用,可以理解效率明显提高,但是要注意的是这里还有一对复制构造函数和析构函数的调用,这是为什么呢?仔细观察可以发现,func函数返回的是(*one),这是一个对象,而不是地址,所以他要调用复制构造函数来创建一个对象的副本,然后在析构。如果我们把func函数的返回类型修改为指针类型的时候就可以减少调用了:

#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 (void)
{
    A a;
    func(&a);

    return 0;
}

这样,执行的结果就是:


这样就达到了对对象作为参数传递程序的最佳优化效果了!







  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++中,函数参数传递可以通过值传递(pass by value)和引用传递(pass by reference)两种方式进行。 值传递: - 值传递是指将实际参数的值复制给形式参数,函数内部对形式参数的修改不影响到实际参数。 - 在函数调用时,创建形式参数的副本,函数对形式参数的操作只影响到副本,并不改变实际参数的值。 - 值传递适用于简单的数据类型,如整型、浮点型、字符型等。 - 值传递的优点是简单、直观,并且不改变原始数据。但对于大型结构体或对象,值传递产生额外的内存开销。 引用传递: - 引用传递是指将实际参数的引用传递给形式参数,函数内部对形式参数的修改影响到实际参数。 - 引用传递通过使用引用作为函数形参,可以直接访问和修改实际参数的值。 - 引用传递适用于需要修改实际参数或传递大型结构体或对象的情况。 - 引用传递的优点是效率高,不产生额外的内存开销,并且可以直接修改实际参数的值。但需要注意引用传递可能对原始数据造成意外的修改。 使用值传递还是引用传递应根据实际情况来决定。一般来说,对于基本数据类型和小型结构体可以使用值传递,而对于大型结构体或需要修改实际参数的情况,应使用引用传递。此外,也可以使用`const`修饰引用参数,以确保函数内部不修改实际参数的值。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值