Mon*_*mer 5 c++ construction rvalue-reference language-lawyer c++11
根据我的理解,以下内容是相同的:
Person p{}; // Case 1
Person p = {}; // Case 1.5
Run Code Online (Sandbox Code Playgroud)
我注意到
Person p = Person{}; // Case 2
Run Code Online (Sandbox Code Playgroud)
产生Case 1与Case 1.5上述及以上相同的跟踪输出。
问题 1:将案例 2 与案例 1 或案例 1.5 进行比较,是因为复制省略还是其他原因?
问题2:以下有什么区别?
Person p{}; // Case 1
Person p = Person{}; // Case 2
Person&& p = Person{}; // Case 3
Run Code Online (Sandbox Code Playgroud)
这三个语句在c++11中并不完全相同。
该语言要求代码存在移动构造函数X x = X{}——否则代码将无法编译。
例如,使用Person如下定义的类:
class Person{
public:
...
Person(Person&&) = delete;
...
};
Run Code Online (Sandbox Code Playgroud)
将无法编译如下语句:
Person p = Person{}; // Case 2
Run Code Online (Sandbox Code Playgroud)
编译器资源管理器上的示例
注意:上面的代码在c++17及更高版本中是完全有效的,因为措辞发生了变化,即使对象不可移动且不可复制,也可以直接在其目标地址中构造对象(这就是人们通常所说的“保证复制省略”) ”)。
第三种情况是临时构造,其生命周期通过绑定到右值引用来延长。在某些情况下,临时对象绑定到右值引用或const左值引用,可以延长它们的生命周期。例如,以下两个构造在绑定到临时生命周期方面是等效的:
Person&& p3_1 = Person{};
const Person& p3_2 = Person{};
Run Code Online (Sandbox Code Playgroud)
就作用域规则而言,它与任何其他自动变量具有相同的生命周期(例如,它将以与将要使用的方式相同的方式在作用域末尾调用析构函数Person person{})。然而,至少在c++11中,构造可以完成的工作与此代码完全不同,即使不存在移动构造函数,此代码也将始终编译(因为这是引用绑定)。Person p2 = Person{}
例如,让我们考虑一个不可移动、不可复制的类型,例如std::mutex. 在C++17中,编写以下代码是有效的:
std::mutex mutex = std::mutex{};
Run Code Online (Sandbox Code Playgroud)
但在C++11中却无法编译。但是,您可以自由地写:
std::mutex&& mutex = std::mutex{};
Run Code Online (Sandbox Code Playgroud)
它创建一个临时变量并将其绑定到一个引用,该引用的生命周期将与此时构造的任何作用域变量相同。
编译器资源管理器上的示例。
注意:故意传播临时对象的生命周期通常不是有意做的事情,但在 C++17 之前,这是使用不可移动对象实现几乎总是自动语法的唯一方法。例如,上面的内容可以重写:auto&& mutex = std::mutex{}
| 归档时间: |
|
| 查看次数: |
213 次 |
| 最近记录: |