这三个语句在c++11中并不完全相同。
案例 2 需要 C++17 之前的移动构造
该语言要求存在用于代码的移动构造函数X x = X{}
-- 否则代码将无法编译。
例如,使用Person
如下定义的类:
class Person{
public:
...
Person(Person&&) = delete;
...
};
将无法编译以下语句:
Person p = Person{}; // Case 2
编译器资源管理器示例
注意:上述代码在c++17及以后版本中完全有效,因为措辞更改允许直接在其目标地址中构造对象,即使是不可移动和不可复制的(这就是人们通常所说的“保证复制省略” ”)。
案例 3 是临时的终身延长
第三种情况是临时构造,其生命周期通过绑定到右值引用来延长。const
在绑定到右值引用或左值引用的某些情况下,可以延长临时对象的生命周期。例如,以下两个构造是等效的,因为它们绑定到临时的生命周期:
Person&& p3_1 = Person{};
const Person& p3_2 = Person{};
就作用域规则而言,它与任何其他自动变量具有相同的生命周期(例如,它将以与将相同的方式在作用域末尾调用析构函数Person person{}
)。然而,至少在c++11中,可以用构造完成的操作与此代码完全不同,即使不存在移动构造函数(因为这是一个引用绑定)Person p2 = Person{}
,该代码也将始终编译。
例如,让我们考虑一个不可移动、不可复制的类型,例如std::mutex
. 在C++17中,编写以下代码是有效的:
std::mutex mutex = std::mutex{};
但是在C++11中编译失败。但是,您可以自由编写:
std::mutex&& mutex = std::mutex{};
它创建一个临时变量并将其绑定到一个引用,该引用的生命周期将与在该点构造的任何作用域变量相同。
编译器资源管理器的示例。
注意:故意传播临时对象的生命周期通常不是故意的,但早在 C++17 之前,这是使用不可移动对象实现几乎总是自动的语法的唯一方法。例如,上面可以重写:auto&& mutex = std::mutex{}