[英]Creating an object by function call in C++
我想通过函数调用创建一个对象,我只会使用一次。
我尝试过的两种方法给出了相同的结果,但由于我是C ++的新手,我不确定它们是否合适。
#include <iostream>
using namespace std;
struct Foo {
Foo(const int x, const int y): x(x), y(y) {};
Foo(Foo & myfoo): x(myfoo.x), y(myfoo.y) {
cout << "copying" << endl;
};
const int x, y;
};
int sum(const Foo & myfoo) {
return myfoo.x + myfoo.y;
}
Foo make_foo(const int x, const int y) {
Foo myfoo (x, y);
return myfoo;
}
int main () {
// version 1
cout << 1 + sum(Foo(2,3)) << endl;
// version 2
cout << 1 + sum(make_foo(2,3)) << endl;
}
以下哪种方法“更正确”? 有什么不同? 我用gcc和clang运行上面的代码,两次都得到了
6
6
这意味着复制构造函数不会被调用。
编辑:谢谢,我已经知道了RVO。 我只是想知道一种方法是否优先于另一种方法
在这种情况下,这两种方法是等效的。
您正在观察的是Copy elision ,或者更具体地说是返回值优化 。
编译器足够聪明,可以识别您不需要构建中间实例,因为您只是要复制,然后销毁它。 因此,它只是创建最终实例,它是函数返回的目标。
语言标准明确允许此优化,即使这意味着您的副本构造函数被绕过。 换句话说,无法保证调用复制构造函数的功能。
不调用复制构造函数,因为在sum(const Foo & myfoo)
, myfoo
通过引用传递,因此不需要复制。 恕我直言我会说,一个普遍适用的Foo
构造函数足以创建一个实例。 如果你有专门的功能会使你的Foo类与构造函数混乱,那么在其他地方有一个函数可能会更优雅,比如Foo loadFooFromFile(string filename)
值得注意的是,通常使用make_*
命名的函数对于需要模板参数的类型非常有用(并且可以在构造期间推导出它们)。
在C ++类中,在调用构造函数时不会推导出模板参数(这将在C ++ 17中更改),因此您必须手动键入它们。 通过创建一个创建对象的函数,您可以自动为其推导出它。
例如,查找std::tuple
或std::pair
我找到了一个非常相关的线程推理功能
在第一种情况下,cout << 1 + sum(Foo(2,3))<< endl; 由于sum接受Foo引用,因此不会调用复制构造函数。 对于以后的情况,您的编译器正在执行RVO,因此不会调用复制构造函数。 有关详细信息,请参阅Return Value Optimization和Copy Elision 。 此问题还有更多细节。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.