Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

std::move and map assignment

I am bit puzzled about how standard governs this case:

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);

Can compilers produce code so that baz will be moved before it's used to initialise and get reference to element in bar (to initialise std::string xxx)? Or is this code safe and there's no undefined behaviour?

like image 851
GreenScape Avatar asked Jan 22 '16 08:01

GreenScape


1 Answers

Hell no. The expression is, yes, equivalent to

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

But there is no guaranteed order between the evaluation of (bar.operator[](baz)).operator= - formally, the postfix-expression designating the function to be called - and the evaluation of the initialization of the argument to operator=, which is what moves from baz.

In fact, 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"));
like image 199
T.C. Avatar answered Dec 10 '22 07:12

T.C.