【问题标题】:Why is private move constructor allowed while initalizing via static method?为什么在初始化静态方法时允许私有移动构造函数?
【发布时间】:2019-08-07 08:10:52
【问题描述】:

sn-p简化代码为:

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;
}

另请参阅我的live example(显示不同编译器的行为)。

最后,我想知道为什么 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 的成员函数,所以它通过了验证。即使怀疑是正确的,我也不确定这是否符合标准。

【问题讨论】:

    标签: gcc clang c++17 rvo nrvo


    【解决方案1】:

    我相信这是P0135: Wording for guaranteed copy elision through simplified value categories 的结果,特别是更改为[dcl.init]

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-17
      • 1970-01-01
      • 2013-11-12
      • 1970-01-01
      • 2012-01-07
      • 1970-01-01
      • 2017-12-07
      • 1970-01-01
      相关资源
      最近更新 更多