返回默认构造值有什么问题吗?
-
01-07-2019 - |
题
假设我有以下代码:
class some_class{};
some_class some_function()
{
return some_class();
}
这似乎工作得很好,省去了我必须声明变量只是为了返回值的麻烦。但我认为我从未在任何类型的教程或参考中看到过这一点。这是编译器特定的东西(Visual C++)吗?或者这是做错了什么?
解决方案
不,这是完全有效的。这也将更加有效,因为编译器实际上能够优化掉临时数据。
其他提示
从函数调用返回对象是“工厂”设计模式,并且被广泛使用。
但是,无论返回对象还是指向对象的指针,您都需要小心。前者将向您介绍复制构造函数/赋值运算符,这可能会很痛苦。
它是有效的,但性能可能并不理想,具体取决于它的调用方式。
例如:
A a;
a = fn();
和
A a = fn();
不一样。
在第一种情况下,调用默认构造函数,然后在需要构造临时变量的 a 上调用赋值运算符。
在第二种情况下,使用复制构造函数。
足够智能的编译器将计算出可以进行哪些优化。但是,如果复制构造函数是用户提供的,那么我看不到编译器如何优化临时变量。它必须调用复制构造函数,并且为此它必须有另一个实例。
Rob Walker 示例之间的差异称为返回值优化 (RVO)(如果您想通过 google 搜索)。
顺便说一句,如果您想确保以最有效的方式返回对象,请使用shared_ptr在堆上创建对象(即通过new)并返回shared_ptr。返回指针并且引用计数正确。
这是完全合理的 C++。
这是完全合法的 C++,任何编译器都应该接受它。是什么让您认为它可能做错了什么?
如果您的类非常轻量级,那么这是最好的方法 - 我的意思是制作它的副本并不是很昂贵。
不过,该方法的一个副作用是,它确实更有可能创建临时对象,尽管这可能取决于编译器优化事物的程度。
对于您想要确保不被复制的更重量级的类(例如大位图图像),那么最好将类似的内容作为参考参数传递,然后填充该参数,只是为了绝对确保不会创建任何临时对象。
总的来说,简化语法和使事情变得更直接可能会产生在表达式中创建更多临时对象的副作用,这是在为更重量级的对象设计接口时应该记住的事情。