Return 构建结构的价值优化和功能
Return Value Optimization and functions that build structures
我有一个函数 "builds" 结构 return:
struct stuff {
int a;
double b;
Foo c;
};
stuff generate_stuff() {
Foo c = generate_foo();
//do stuff to Foo, that changes Foo:
//...
return {1, 2.0, c}; //should this be return {1, 2.0, move(c)};?
}
我是否应该将 c
移出函数?我意识到,(N)RVO 经常可以就地构建对象,但有时情况并非如此。什么时候不能完成 (N)RVO,因此,我什么时候应该移动函数的对象?
换句话说,这显然是 returned 的临时文件的 RVO。问题是,c
会发生 NRVO(名为 return 值优化)吗?将 c
就地构造(在函数的调用位置,在临时 stuff
结构内),还是将 c
在函数中构造,然后复制到结构中调用站点。
您对 move(c)
的调用并没有将 c 移出函数,而是将其移入从函数 return 编辑的临时结构中。临时 return 值应始终受益于 RVO。但是,我相信 c 的 move/copy 不能被优化掉,因为 c 本身不是临时的。所以在这里移动版本应该至少和复制版本一样高效(测试了 g++、clang++ 和 MVC++ 的简单场景)。
如果你必须绝对减少 copy/move 操作的数量,那么你可以写
struct stuff {
int a;
double b;
Foo c;
};
stuff generate_stuff() {
stuff s{ 1, 2.0, generate_foo() };
//use s.c instead of c
//...
return s;
}
由于 NRVO,这将导致只有一个 Foo 结构而没有 copies/moves。
编辑:
正如@dyp 在对您的问题的评论中指出的那样,Stuff 的就地构造实际上并不是 RVO 的情况,而是标准所要求的。无论如何,重要的部分是 c
的 move/copy 不能省略,因此使用 move
永远不会导致性能下降。
我有一个函数 "builds" 结构 return:
struct stuff {
int a;
double b;
Foo c;
};
stuff generate_stuff() {
Foo c = generate_foo();
//do stuff to Foo, that changes Foo:
//...
return {1, 2.0, c}; //should this be return {1, 2.0, move(c)};?
}
我是否应该将 c
移出函数?我意识到,(N)RVO 经常可以就地构建对象,但有时情况并非如此。什么时候不能完成 (N)RVO,因此,我什么时候应该移动函数的对象?
换句话说,这显然是 returned 的临时文件的 RVO。问题是,c
会发生 NRVO(名为 return 值优化)吗?将 c
就地构造(在函数的调用位置,在临时 stuff
结构内),还是将 c
在函数中构造,然后复制到结构中调用站点。
您对 move(c)
的调用并没有将 c 移出函数,而是将其移入从函数 return 编辑的临时结构中。临时 return 值应始终受益于 RVO。但是,我相信 c 的 move/copy 不能被优化掉,因为 c 本身不是临时的。所以在这里移动版本应该至少和复制版本一样高效(测试了 g++、clang++ 和 MVC++ 的简单场景)。
如果你必须绝对减少 copy/move 操作的数量,那么你可以写
struct stuff {
int a;
double b;
Foo c;
};
stuff generate_stuff() {
stuff s{ 1, 2.0, generate_foo() };
//use s.c instead of c
//...
return s;
}
由于 NRVO,这将导致只有一个 Foo 结构而没有 copies/moves。
编辑:
正如@dyp 在对您的问题的评论中指出的那样,Stuff 的就地构造实际上并不是 RVO 的情况,而是标准所要求的。无论如何,重要的部分是 c
的 move/copy 不能省略,因此使用 move
永远不会导致性能下降。