#include <utility>
struct A {};
struct B {
B(A&&) {}
B(const B&) = delete;
};
static void func(B) {}
int main() {
A a;
func(std::move(a));
}
此程序被接受:
- 自 7.1 以来的 GCC 与
-std=c++17
- GCC 主干(可能默认使用 C++17?)
- 从 5.0 开始使用
-std=c++17
- MSVC 我能找到的所有版本。
C++17 中关于此的标准是否发生了变化? MSVC 在 C++17 之前接受这个是错误的吗?
最佳答案
MSVC 错误。对于 guaranted copy elision自 C++17 以来,
The objects are constructed directly into the storage where they would otherwise be copied/moved to. The copy/move constructors need not be present or accessible:
- In the initialization of an object, when the initializer expression is a prvalue of the same class type (ignoring cv-qualification) as the variable type:
给定func(std::move(a));
,std::move(a)
用于构造一个临时的B
首先通过 B::B(A&&)
,然后通过 B::B(const B&)
将临时对象作为参数复制到 func
>。完全省略复制操作,参数由std::move(a)
直接通过B::B(A&&)
构造。
在 C++17 之前,这是一种优化,复制/移动构造函数仍然必须存在且可访问。
关于c++ - 编译器在 std::move 和 deleted 复制构造函数方面的行为不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67226687/