gpt4 book ai didi

c++ - RVO、移动操作和困境

转载 作者:可可西里 更新时间:2023-11-01 17:52:27 31 4
gpt4 key购买 nike

在过去一天左右的时间里,我一直在学习移动构造函数,试图坚持大多数人似乎建议的按值(value)返回的一般规则,并且遇到了一个有趣的(对我而言)困境。

假设我有一个昂贵的构造/复制类“C”,它具有正确定义的复制构造函数、赋值运算符、移动构造函数和移动赋值运算符。

首先,这段代码如我所料省略了复制构造函数:

C make_c1() {
return C();
}

这样做:

C make_c2() {
C tmp;
return tmp;
}

这也是(无论我传递 1 还是 2):

C make_c3(int a) {
return a == 1 ? make_c1() : make_c2();
}

当我谈到这里时,我遇到了一个问题:

C make_c4(int a) {
C tmp;
return a == 1 ? make_c1() : tmp;
}

传入 1 会触发 make_c1 结果的 RVO,但传入 2 会触发 tmp 上的复制构造函数。

将函数修改为以下内容会导致为 tmp 触发移动构造函数:

C make_c5(int a) {
C tmp;
return a == 1 ? make_c1() : std::move(tmp);
}

一切都很棒,除了...

在这些简单的示例中,RVO 的触发与我所希望的差不多。

但是,如果我的代码稍微复杂一些并且在某些编译器上不会在最后一个函数中调用 RVO 怎么办?在这种情况下,我需要将对 make_c1 的调用包装在 std::move 中,这将降低代码在那些确实调用 RVO 的编译器上的效率。

所以我的问题是:

  1. 当我返回本地对象时,为什么没有在 make_c4 中调用移动构造函数? (毕竟快要毁了)。
  2. 在函数 make_c5 中,我应该按值还是移动返回 make_c1 的结果? (避免不同编译器/平台的代码版本不同)。
  3. 是否有更好的方法对最终函数进行编码,使其为合理的编译器实现做正确的事情?

我一直使用的编译器是 Cygwin 上的 GCC 4.5.3。

最佳答案

隐含的 move-on-return 仅在 RVO 合法的相同上下文中合法。当表达式是非 volatile 自动对象(函数或 catch 子句参数除外)的名称时,RVO 是合法的,并且具有与函数返回类型相同的 cv- 非限定类型([class.copy]/p31/b1 ).

如果将 make_c4 转换为:

C make_c4(int a) {
C tmp;
if (a == 1)
return make_c1();
return tmp;
}

然后您将获得调用 make_c4(2) 的预期移动构造。由于您陈述的原因,您的 make_c5 重写是不可取的。

更新:

我还应该包括对 [expr.cond]/p6/b1 的引用,它解释了当第二个表达式是纯右值而第三个是左值时条件表达式的语义,但它们具有相同的类型:

The second and third operands have the same type; the result is of that type. If the operands have class type, the result is a prvalue temporary of the result type, which is copy-initialized from either the second operand or the third operand depending on the value of the first operand.

即本段指定条件的结果纯右值是 copy-initialized,来自示例中的第三个参数。 复制初始化 在 [dcl.init]/p14 中定义。当复制初始化的源是类类型左值时,这将调用该类型的复制构造函数。如果源是右值,它将调用移动构造函数(如果存在),否则它将调用复制构造函数。

条件表达式的规范不允许从左值参数进行隐式移动,即使条件表达式是返回表达式的一部分。语言有可能被设计成允许这样一个隐式的移动,但据我所知,它从未被提议过。此外,条件表达式的现有规范已经非常复杂,使得语言的这种改变更加困难。

关于c++ - RVO、移动操作和困境,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7851021/

31 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com