来自cppreference的move page
除非另有说明,否则所有标准库对象都有 已被移动的位置处于有效但未指定的状态。那是, 只有没有先决条件的函数,例如赋值 操作符,可以在从
移出后在对象上安全使用
因此,从同一页面上的示例中,下面的代码被视为未定义的行为
vector<string> v_string;
string example = "example";
v_string.push_back(move(example));
cout << example << endl;
MSVC将在控制台上不输出任何内容,但如果我这样做
vector<int> v_int;
int number = 10;
v_int.push_back(move(number));
cout << number << endl;
将输出10.这是否有原因?或者它总是未定义的行为?
答案 0 :(得分:10)
未指定并不代表未定义。
根据C ++ 11标准,第17.3.26节:
有效但未指定的状态 除了满足对象的不变量并且对象上的操作按其类型指定的行为
之外,未指定的对象状态
当对象处于有效状态时,您可以将其流式传输到输出,因为流没有其他前提条件。然而打印的是未指定的,所以它可能只打印任何东西,或打印出你父亲闻到的接骨木果。您不能安全地做的是使用具有附加前提条件的函数,例如back()
,此外还需要字符串非空。有效字符串可以为空。
对于未指定但有效的状态,包含旧值是完全可接受的选项。对于int
等基本类型,简单副本只是执行移动的最有效方式。
还应该注意int
不是标准库对象,而是基本类型(如3.9.1节所定义)。因此,您的报价不适用。
答案 1 :(得分:3)
这是因为string
可以通过窃取指向实际字符的指针来有效move
d,这就是编译器所做的事情,从{move
d离开1}}&#34;空&#34;。 string
无法有效int
d,您只需复制一份。因此旧的move
仍在那里。但这是没有记录的。只是不要使用int
编辑过的对象,不要依赖于未指定的行为。
答案 2 :(得分:0)
未定义的行为仅仅意味着
本国际标准没有要求的行为。 允许的未定义行为包括忽略这种情况 完全具有不可预测的结果,在翻译过程中表现出色 或者以文件化的方式执行程序 环境(有或没有发出诊断信息),到 终止翻译或执行(发布a 诊断信息)。许多错误的程序结构不会产生 未定义的行为;他们需要被诊断出来。
如果您有兴趣,请查看"What every C programmer should know about undefined behavior"。这真是令人大开眼界。
在您的情况下,它不是未定义的行为,而是未指定的状态: 在21.4.2.16中,C ++标准定义了移动构造函数的语义:
构造一个basic_string类的对象,如表69所示。 存储的分配器由alloc构造。在第二种形式中,str保持在具有未指定值的有效状态。
&#34;第二种形式&#34;是移动构造函数,因此字符串处于未指定状态。
这意味着对象必须处于满足不变量的状态,但未指定任何其他内容。对于字符串,任何内容都可以。