2016-08-24 17 views
11

Czy poniższe elementy są dobrze zdefiniowane?vector.assign() z wartością w sekwencji

std::vector<std::string> v{"test"}; 
v.assign(1, v.at(0)); 

Jeśli stary sekwencję zniszczone przed nowym jest wykonana odniesienie przekazywane assign będzie unieważniony a więc program będzie źle uformowane.

Czy standard wspomina o tym przypadku (wartość będącym częścią starej sekwencji) lub coś podobnego w dowolnym miejscu, czyniąc ten konstrukt dobrze uformowanym? Nie mogłem nic znaleźć.

Z kopią standardowej implementacji biblioteki Dinkumware jest dostarczany z VS2010 (_Assign_n jest to, co nazywa się wewnętrznie przez assign):

void _Assign_n(size_type _Count, const _Ty& _Val) 
{ // assign _Count * _Val 
    _Ty _Tmp = _Val; // in case _Val is in sequence 
    erase(begin(), end()); 
    insert(begin(), _Count, _Tmp); 
} 

Komentarz

w przypadku _Val jest kolejno

sugeruje, że albo standard wyraźnie stwierdza, że ​​przypisanie elementu, który jest częścią , aktualna sekwencja jest dobrze uformowana, lub że implementacja Dinkumware po prostu stara się być inteligentna;)

Która to jest?

+1

Jestem zaskoczony, że nie wystarczy napisać 'void _Assign_n (size_type _count, _Ty Val)', ale oczywiście wyprzedza VS2010 C++ 11. W dzisiejszych czasach naprawdę nie powinieneś przyjmować "const &" kiedy potrzebujesz kopii. Zapobiega ruchom. – MSalters

Odpowiedz

9

To zachowanie jest niezdefiniowane, kopiowany element nie może pochodzić od samego pojemnika.

[sequence.reqmts] Tabela 84 (projekt n4606)

enter image description here

+2

Zauważ, że [LWG 2705] (http://wg21.link/lwg2705) ma na celu usunięcie warunku. – cpplearner

1

at() zwraca odniesienie do istniejącej wartości w kontenerze. Jako takie jest to niezdefiniowane zachowanie.

Można zrobić to dobrze zdefiniowane zachowanie po prostu poprzez jego kopię:

v.assign(1, (std::string)v.at(0)); 
+0

To było dobrze znane. Pytanie brzmi, czy standard mówi coś, czy nie, o tym zachowaniu. –