我知道标题听起来很熟悉,因为有很多类似的问题,但我问的是问题的不同方面(我知道将事物放在堆栈上和将它们放在堆上之间的区别)。
在 Java 中,我总是可以返回对“本地”对象的引用
public Thing calculateThing() { Thing thing = new Thing(); // do calculations and modify thing return thing; }
在 C++ 中,做类似的事情我有 2 个选项
(1) 当我需要“返回”一个对象时,我可以使用引用
void calculateThing(Thing& thing) { // do calculations and modify thing }
然后像这样使用它
Thing thing; calculateThing(thing);
(2) 或者我可以返回一个指向动态分配对象的指针
Thing* calculateThing() { Thing* thing(new Thing()); // do calculations and modify thing return thing; }
Thing* thing = calculateThing(); delete thing;
使用第一种方法我不必手动释放内存,但对我来说它使代码难以阅读。第二种方法的问题是,我必须记住 to delete thing;,这看起来不太好。我不想返回复制的值,因为它效率低下(我认为),所以问题来了
delete thing;
我不想返回复制的值,因为它效率低下
证明给我看。
查找 RVO 和 NRVO,以及 C0x 移动语义。在 C03 中的大多数情况下,out 参数只是让代码变得丑陋的好方法,而在 C++0x 中,使用 out 参数实际上会伤害自己。
只需编写干净的代码,按值返回。如果性能是一个问题,请对其进行分析(停止猜测),然后找出可以解决的方法。它可能不会从函数返回东西。
就是说,如果你死心塌地那样写,你可能想要做 out 参数。它避免了动态内存分配,这更安全且通常更快。它确实需要您在调用函数之前有某种方法来构造对象,这并不总是对所有对象都有意义。
如果要使用动态分配,至少可以将其放入智能指针中。(无论如何都应该这样做)然后你不用担心删除任何东西,事情是异常安全的,等等。唯一的问题是它可能比按值返回慢!