0

Рассмотрим следующую программу:Move семантика в присутствии оснований виртуальных

#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) и лязг ++ и печатать различные значения для C1 и C2, тогда как Visual Studio 2013 и 2015 последовательно печати последовательность алфавитов в нижнем регистре как для C1, так и для C2.

Кто такой? или это просто какая-то петля в стандарте?

+1

Полезное предупреждение от clang: оператор присваивания по умолчанию с 'C' переместит присвоение виртуального базового класса' Name' несколько раз – 0x499602D2

+0

@ 0x499602D2 мой вопрос по-прежнему остается :-) Кто прав? или нет правильного ответа? – ForeverLearning

+1

Похож на UB. 'c1 = f()' переходит из временного, созданного 'f()' дважды. – 0x499602D2

ответ

3

С §12.8/28 [class.copy]:

Не определено ли подобъектов, представляющие виртуальные классы базовых назначены несколько раз оператором присваивания в неявно определенных копирования/перемещения. [Пример:

struct V { }; 
struct A : virtual V { }; 
struct B : virtual V { }; 
struct C : B, A { }; 

Не определено ли виртуальный базовый класс подобъектом V назначается дважды оператором присваивания неявно определенной от копирования/перемещения для C. - конец примера]

Поведение вашей программы не определено в соответствии со стандартом. Visual Studio решает вызвать оператор присваивания один раз, когда GCC и Clang делают это дважды. Результат операции перемещения оставляет объект перехода в действительном, но неуказанном состоянии, поэтому впоследствии переход от временного снова оставит s с неопределенным значением, но в приведенном выше предложении это разрешено. Поэтому, чтобы ответить на ваш вопрос, нет правильного поведения для этой программы.

+0

Не «неопределенное значение». –

+0

@ T.C. Должна ли она быть «неуказанной»? – 0x499602D2

+0

Да, первое назначение перемещения оставляет 's' в действительном, но неуказанном состоянии; переместить назначение из чего-либо с действительным, но неопределенным состоянием, делает пункт назначения также действительным, но неопределенным. –