为什么 CopyConstructible 定义提到“常量 T 的右值表达式”?

Why CopyConstructible definition mention "rvalue expression of const T"?

提问人:code707 提问时间:7/18/2018 最后编辑:curiousguycode707 更新时间:7/23/2018 访问量:79

问:

以下是 cpppreference 的定义:

[https://en.cppreference.com/w/cpp/named_req/CopyConstructible][1]

要求:类型 T 满足 CopyConstructible,如果

类型 T 满足 MoveConstructible 和 Given

v,类型为 T 或常量 T 的左值表达式或右值表达式 类型 const T u,任意标识符 以下表达式 必须有效并具有其指定的效果

表达式后置条件 T u = v;你的价值相当于 v 的值。v 的值保持不变

T(v) T(v) 的值等于 v 的值。v 的值 没有变化。

我的问题是以下几行:

v,类型为 T 或常量 T 的左值表达式或右值表达式 类型 const T

我不明白这个“常量 T 类型的右值表达式”的一部分?为什么这个“const T 类型的右值表达式”出现在 CopyConstructible 的定义中?有人可以举例解释一下吗?MoveConstructible 的定义(这是 CopyConstructible 的前提条件)已经包含了该要求,不是吗?

C++ 常量 language-lawyer copy-constructor

评论


答:

5赞 Caleth 7/18/2018 #1

不,MoveConstructible 的定义只关心非 const 右值表达式,因为你不能从 const 移动。

CopyConstructible 扩展了它以涵盖 和 的其余可能性。T u = v;T(v);

请注意,如果仅复制类型保持不变,则它仍然满足 MoveConstructible,因为“新值未指定”涵盖了这一点。rvrv

举个例子

struct Foo {
    void Bar() { /* modify Foo somehow */ }
};

const Foo createFoo() { return {}; }

Foo foo = createFoo(); // Must copy, as the return value is const

这种构造发生在 C++11 之前的代码中,作者希望禁止构造,因为修改临时 .createFoo().Bar();Foo

评论

0赞 code707 7/18/2018
谢谢。它解释得很好。
0赞 Daniel Langr 7/18/2018 #2

只是一个在 C++11/14 中产生错误的示例,因为是 MoveConstructible 而不是 CopyConstructibleX

struct X {
   X() = default;
   X(const X&) = delete;
   X(X&&) = default;
};

const X f1() { return X{}; }
X f2() { return X{}; }

int main() {
   X x1 = f1(); // copy-initialization from const rvalue: ERROR
   X x2 = f2(); // copy-initialization from rvalue: OK
}

请注意,在 C++17 中没有错误,因为只调用了默认构造函数。