C++函数返回对象效率以及使用建议

探讨C++中函数返回对象的机制与编译器优化,包括传值和传引用的区别,以及如何利用RVO(Return Value Optimization)优化性能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

函数的传参和传返回值,分为两种模式:传值和传引用。

传值就是传整个对象,传引用就是传对象的引用(地址)。当对象本身比较小时,可以直接传值,但当对象比较大时我们一般会传引用以节省内存和减少拷贝。这是C++的机制,在java中都是传引用,所以不用像C++一样区分值语义和引用语义。

对于传参一般建议都使用传引用,但对于返回值而言,我们不能直接返回对象引用,因为,函数调用完后会清栈,引用指飞。但传值我们又担心临时变量的拷贝降低性能,所以我们可能写出如下代码,返回值用指针包裹。

shared_ptr<A> fun()
{
    make_shared<A> ptr;
    ...
    return ptr;
}

这当然万无一失,但明显变麻烦了。实际上我们可以放心大胆地返回对象。下面进行论述:

C/C++函数返回对象的原理:

A fun2()
{
    A a1();
    ...
    return a1;
}
void fun1()
{
    A a2=fun2();
}

a1是在函数fun2中堆栈中的对象,在return时,会将其拷贝构造到外层函数fun1的堆栈中(这个对象是一个匿名对象,是一个右值,马上会被析构),之后将其拷贝构造产生对象a2。这是没有任何编译器优化的情况。

一般情况下,编译器会采用RVO(return value optimization)优化,参看《深度探索C++对象模型》。下面是一个例子

//原函数
Point3d factory()
{
    Point3d po(1,2,3)
    return po;
}
int main()
{
    Point3d p = factory();
    return 1;
}

//
编译器优化后的示例代码
//
factory(const Point3d &_result)
{
    Point3d po;
    po.Point3d::Point3d(1,2,3);
    _result.Point3d::Point3d(po);   //用po拷贝构造_result;
    po.Point3d::~Point3d();         //po对象析构
    return;
}
int main()
{
    Point3d _result;
    factory(_result);
    Point3d p=result;
    return 1;
}

大体意思是说,会在值传递返回值的函数中,将返回值改写成传引用参数。这样可以少一次临时变量的构造。这是编译器优化时帮我们做的。

总结起来就是放心大胆地返回一个对象实体,这并不会有多余的开销,编译器会帮我们优化。


 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值