C++ 为什么可复制的定义提到;常数T的右值表达式;?

C++ 为什么可复制的定义提到;常数T的右值表达式;?,c++,constants,language-lawyer,copy-constructor,C++,Constants,Language Lawyer,Copy Constructor,以下是参考文献中的定义: [ 要求:T型满足可复制的条件 类型T满足可移动可构造性,并且 v、 类型为T或常量T的左值表达式或右值表达式 const T u类型的任意标识符包含以下表达式 必须有效并具有指定的效果 条件tu=v后的表达式;u的值等于 v的值。v的值不变 T(v)的值等于v的值 没有变化 我的问题如下: v、 类型为T或常量T的左值表达式或右值表达式 常数T型 我不理解这个“常量T类型的右值表达式”的一部分?为什么这个“常量T类型的右值表达式”存在于CopyConstructibl

以下是参考文献中的定义:

[

要求:T型满足可复制的条件

类型T满足可移动可构造性,并且

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

条件tu=v后的表达式;u的值等于 v的值。v的值不变

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

我的问题如下:

v、 类型为T或常量T的左值表达式或右值表达式 常数T型

我不理解这个“常量T类型的右值表达式”的一部分?为什么这个“常量T类型的右值表达式”存在于CopyConstructible的定义中?有人能举例说明吗?MoveConstructible的定义(这是CopyConstructible的先决条件)已经包含了这个要求,不是吗?

不,定义只关心非常量值表达式,因为不能从常量移动

CopyConstructible扩展了这一功能,以涵盖
tu=v;
T(v);
的其余可能性

请注意,如果仅复制类型保持
rv
不变,则仍然满足MoveConstructible,因为“未指定
rv
的新值”

例如

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
是一个错误,这只是在C++11/14中产生错误的一个示例,因为
X
是可移动构造的,而不是可复制构造的:


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

谢谢。解释得很好。
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
}