我刚在单元测试代码中发现这是一个错误类型:
Binding binding(x, y, z);
Binding moved(std::move(moved)); // Should be `std::move(binding)`
为什么这个有效的代码?这里发生了什么?这不是一个错误吗?
#include <string>
#include <iostream>
int main() {
std::string x(std::move(x));
std::cout << '"' << x << '"' << std::endl;
}
答案 0 :(得分:5)
它是有效的 * (取决于Binding
的定义),因为声明的名称是从声明点开始就知道的。
E.g。
struct Node { Node* next; int value; };
是同一个一般原则的一个例子,
Node head = {&head, 0};
是使用(或滥用)该想法的变量声明的更直接的例子。
* 如果代码调用通常的移动构造函数,它试图从未初始化的对象移动,那么这是未定义的行为,在这个意义上是无效的。
答案 1 :(得分:4)
为什么这个有效的代码?
不是。它在语法上是有效的,但具有未定义的行为(假设构造函数使用其参数)。
这里发生了什么?
假设移动构造函数的行为与预期的一样,moved
使用自己的未初始化值进行初始化。使用未初始化的值会产生未定义的行为。
这不应该是一个错误吗?
也许,但事实并非如此。您可以在其初始化程序中访问变量的名称,只要您不使用该值,该名称就是合法的。例如,这个:
void * p = &p;
是明确定义的,初始化一个指向自身的指针。
由于它是通过引用传递给用户声明的构造函数,因此编译器无法判断该值是否可以使用,因此无法发出警告。