3

简化的代码片段是:

class A {
  public:
    ~A();
    static A create();

  private:
    A() = default;
    A(A&&) = default;
    NonCopyable n;
};

A A::create() {
  A a;
  return a;
}

int main(int argc, char* argv[]) {
  auto a = A::create();
  return 0;
}

另请参阅我的实时示例(显示不同编译器的行为)。

最后,我想知道为什么auto a = A::create();使用较新的编译器 [gcc >= 7.1] 编译没有错误(C++17 标准的哪一部分与这里相关?),因为:

  1. 我们有一个不可复制的成员NonCopyable n;,因此默认的复制构造函数格式不正确。
  2. 这是一个 NRVO,因为A a; return a;标准不保证复制省略。
  3. 移动构造函数A(A&&)被标记为私有。
  4. 优化已关闭-O0以进行测试。

我的怀疑是编译器正在“验证”移动构造函数return a;;因为这是它的成员函数,A所以它通过了验证。即使怀疑是正确的,我也不确定这是否符合标准。

4

1 回答 1

2

我相信这是P0135 的结果:通过简化值类别保证复制省略的措辞,特别是对[dcl.init]的更改:

  • 如果初始化表达式是纯右值并且源类型的 cv 非限定版本与目标类是同一类,则初始化表达式用于初始化目标对象。[示例: T x = T(T(T()));调用T默认构造函数进行初始化x。— <em>结束示例]

因此,此行为不依赖于返回值的复制省略或移动构造函数的可用性。

于 2019-08-07T08:28:22.627 回答