【发布时间】:2015-05-12 14:48:57
【问题描述】:
考虑以下程序:
#include <iostream>
#include <ostream>
#include <string>
#include <utility>
using namespace std;
struct Name { string s; Name(string s) : s(move(s)) { } };
struct A : virtual Name { A(string s) : Name(move(s)) { } };
struct B : virtual Name { B(string s) : Name(move(s)) { } };
struct C : A, B { C(string s) : A(string()), B(string()), Name(move(s)) { } };
C f() { return C("abcdefghijklmnopqrstuvwxyz"); }
int main()
{
C c1("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
C c2("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
C ff = f();
c1 = f();
c2 = ff;
cout << "C1 = " << c1.s << " " << "C2 = " << c2.s << "\n";
return 0;
}
gcc (4.9.2) (http://ideone.com/G7uzCQ) 和 clang++ 都为 C1 和 C2 打印不同的值,而 Visual Studio 2013 和 2015 始终为 C1 和 C2 打印小写字母序列。
谁是对的?还是只是标准中的一些漏洞?
【问题讨论】:
-
来自 clang 的有用警告:
C的默认移动赋值运算符将多次移动分配虚拟基类Name -
@0x499602D2 我的问题仍然存在 :-) 谁是对的?还是没有正确答案?
-
看起来像 UB。
c1 = f()两次从f()产生的临时移动。 -
@0x499602D2 至少在语义上,我看到了 VS 2013/2015 的“正确”输出。我猜是因为它的 UB,我看到什么并不重要,因为没有真正的答案?
标签: c++11 move-semantics virtual-inheritance diamond-problem