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