C++对象的返回 - 最佳实践

7

我是一名新手C++程序员,现在遇到了以下问题:

想象你有一个函数,它创建一个新对象并返回该对象。这种情况下最好的方法是什么? 我找到了三种不同的解决方案。

解决方案1 使用拷贝构造函数

MyClass getMyClass() {
    MyClass obj;
    //work with obj, set values...
    return obj;
}

据我所理解,您创建了一个新对象,复制该对象,销毁第一个对象并返回复制的对象。因此,我创建了两个对象,但我只需要一个。是这样吗? 解决方案2:在堆上创建对象并使用指针。
MyClass* getMyClass() {
    MyClass* obj = new MyClass();
    //work with obj, set values...
    return obj;
}

这似乎是最糟糕的解决方案,你必须自己进行内存管理。

解决方案3 将对象作为参数传递

MyClass getMyClass(MyClass& obj) {
    //work with obj, set values...
    return obj;
}

你需要创建一个默认对象并在函数中设置所有值。
我也考虑过使用unique_ptr<MyCLass>,但是有同样的问题,即当函数作用域结束时unique_ptr会被销毁。

你应该考虑使用shared_ptr http://www.cplusplus.com/reference/memory/shared_ptr/,同时你也可以使用移动语义http://www.cplusplus.com/reference/algorithm/move/。 - Florian Groetzner
对于解决方案1,编译器应该能够应用命名返回值优化并在其最终位置构造对象。 - Michael
对于解决方案2,请使用std::shared_ptr。这三个解决方案都有它们的用例,通常没有一个是更好的选择。 - πάντα ῥεῖ
“当函数作用域结束时,unique_ptr 将被销毁,除非你从函数中返回它。unique_ptr 是可移动的。” - Mike Seymour
@Youda008 是的,你说得对。 - Ennosigaeon
显示剩余3条评论
2个回答

9
解决方案1没有使用拷贝构造函数,而是采用返回值优化。这意味着在函数中构造的对象实际上并没有被复制,而是直接传递给调用函数的程序。对于非多态对象(即没有继承关系)且在堆栈上不占用太多空间的情况下,解决方案1是一个非常好的选择。
对于多态对象,首选方法应该是解决方案2。但是始终要考虑谁拥有您的对象,即谁负责调用delete。一个很好的替代方法是使用shared_ptrunique_ptr
解决方案3实际上并没有创建对象,它只是在已经创建的对象上进行操作。在这里返回对象也没有意义。

0

每个函数都有自己的用途,不能说其中一个在所有情况下都比另一个更好或更差。这完全取决于你的对象,你如何创建它们,它们应该接口到哪里以及它们在哪里使用。

还有第四种方法,通过使用共享指针shared_ptr(如果需要共享所有权)或自动指针(unique_ptrauto_ptr(已经过时))返回。

例如,使用引用的函数不需要返回对象,这是一项额外的操作。

返回指针的函数可能不需要包含头文件,简单的前向声明就足够了(至少在头文件中声明函数时)。但是,当然,这将需要手动管理内存(再次:共享指针可能会在这里有所帮助)。


仅有前向声明是不足以使用 new 构造一个对象的。 - DevSolar
@DevSolar编辑了问题(正在进行的工作) - Ferenc Deak
为什么要使用shared_ptr?我看不出需要共享所有权的建议。 - juanchopanza
1
不用太在意,这个问题已经是一个重复的了。 - DevSolar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接