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 永远不会导致性能下降。