cppref 里对于复制消除的解释:
从 C++17 起,非必须不会将纯右值实质化,并且它会被直接构造到其最终目标的存储中。这有时候意味着,即便语言的语法看起来进行了复制/移动(例如复制初始化),也并不进行复制/移动——这表示该类型完全不需要具有可访问的复制/移动构造函数。其例子包括:
- 在对象的初始化中,当初始化器表达式是一个与变量类型相同(忽略 cv 限定)的类类型的纯右值时
n
的初始化分成两步:
- 调用转换构造函数
atomic<int>(int i);
产生纯右值对象; - 调用拷贝构造函数将临时对象拷贝到
n
中。
在 C++17 以后,由于复制消除第二步并不会执行,也就是不会调用拷贝构造,而是直接将产生的纯右值构造到 n
中,所以就算 atomic
的拷贝构造函数指定为删除,仍然能正常初始化 n
。
而在 17 以前,复制消除非强制并且各大编译器都未实现,所以不能通过编译。