c++ - 返回值优化和构建结构的函数

标签 c++ c++11 move rvo

我有一个函数可以“构建”一个要返回的结构:

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,因此,什么时候应该 move 函数的对象?

换句话说,这显然是返回的临时对象的 RVO。问题是,c 会发生 NRVO(命名返回值优化)吗? c 是就地构造(在函数的调用点,临时 stuff 结构内),还是 c 构造在函数,然后复制到调用站点的结构中。

最佳答案

您对 move(c) 的调用并不是将 c 移出函数,而是将其移入从函数返回的临时结构中。临时返回值应始终受益于 RVO。但是,我相信 c 到临时的 move/复制不能被优化掉,因为 c 本身不是临时的。所以在这里 move 版本应该至少和复制版本一样高效(测试了 g++、clang++ 和 MVC++ 的简单场景)。

如果你必须绝对减少复制/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 的单一构造,并且没有复制/move 。

编辑: 正如@dyp 在对您的问题的评论中指出的那样,Stuff 的就地构造实际上并不是 RVO 的情况,而是标准所要求的。无论如何,重要的部分是不能省略 c 的 move/复制,因此使用 move 永远不会导致性能下降。

关于c++ - 返回值优化和构建结构的函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28953854/

相关文章:

c# - 将结构数组从 C#(.NET Core) 传递到 C++(unamnaged)

c++ - VS 2010下编译C代码

c++ - 覆盖非虚函数

c++ - 我可以从 C 调用 std::function 吗?

c++ - 为什么我的性能计数器代码不起作用?

c++ - 通过引用将参数传递给 std::async 失败

c++ - 循环包括由于 C++ 类中的枚举

c++ - 右值参数导致的多重实现

python - 在pygame中将玩家 move 到鼠标位置

c++ - 使用左值映射 move 位置