2016-01-22 15 views
6

Jestem nieco zaskoczony, jak standardowy podlega niniejsza sprawa:std :: ruch i mapa przypisanie

struct Foo { 
    Foo & operator = (std::string xxx) 
    { 
     x = std::move(xxx); 
     return *this; 
    } 

    std::string x; 
}; 

std::map<std::string, Foo> bar; 

std::string baz = "some string"; 

bar[baz] = std::move(baz); 

Czy kompilatory produkować kod, tak aby baz zostanie przeniesiony przed jest używany do zainicjowania i uzyskać odniesienie do elementu w bar (aby zainicjować std::string xxx)? A może ten kod jest bezpieczny i nie ma niezdefiniowanego zachowania?

+1

To nie UB, ale nie są gwarantowane do pracy, albo. –

+0

Zobacz [this] (http://coliru.stacked-crooked.com/a/5ef8993192148d84) uproszczoną wersję swojego kodu. 'std :: map' i operator przypisania nie muszą być zaangażowani, aby to nastąpiło, a ich obecność nie zmienia podstawowego problemu z kodem. – Mankarse

+0

@Mankarse, tak, rzeczywiście, wszystko można sprowadzić do tego przypadku. – GreenScape

Odpowiedz

11

Piekło nie. Wyrażenie jest tak, odpowiednik

(bar.operator[](baz)).operator=(std::move(baz)) 

Ale nie ma gwarantowane porządek między oceną (bar.operator[](baz)).operator= - Formalnie postfix-ekspresja wyznaczające funkcję nazwać - a ocena inicjalizacji Argument do operator=, czyli co porusza się od baz.

W rzeczywistości this asserts on GCC:

std::map<std::string, Foo> bar; 
std::string baz = "some string"; 
bar[baz] = std::move(baz); 
assert(bar.count("some string")); 
+1

Dziękuję! Tak właśnie myślałem, chciałem tylko potwierdzenia od kogoś innego. – GreenScape

Powiązane problemy