#include <iostream>
#include <string>
#include <map>
struct A {
int n { 42 };
std::string s { "ciao" };
};
int main() {
A a;
std::map<std::string, A> m;
std::cout << "a.s: " << a.s << std::endl; // print: "a.s: ciao"
m.emplace(a.s, std::move(a)); // a.s is a member of a, moved in the same line
std::cout << "in map: " << m.count("ciao") << std::endl; // print: "in map: 1"
std::cout << "a.s: " << a.s << std::endl; // print: "a.s: " (as expected, it has been moved)
}
Is it safe to pass as an argument a member of a "moving" object? In this case, emplace seems to work: the map has the expected key.
Interesting. I think it's safe, for convoluted reasons. (For the record, I also consider it very bad style -- an explicit copy costs you nothing here, since it will be moved into the map.)
First of all, the actual function call is not a problem. std::move
only casts a
to an rvalue reference, and rvalue references are just references; a is not immediately moved. emplace_back
forwards its parameters to a constructor of std::pair<std::string, A>
, and this is where things get interesting.
So, which constructor of std::pair
is used? It has rather many, but two are relevant:
pair(const T1& x, const T2& y);
template<class U, class V> pair(U&& x, U&&y);
(See 20.3.2 in the standard), where T1
and T2
are the template arguments of std::pair
. As per 13.3, we end up in the latter with U == const T1&
and V == T2
, which makes intuitive sense (otherwise moving into a std::pair
would be effectively impossible). This leaves us with a constructor of the form
pair(const T1& x, T2 &&y) : first(std::forward(x)), second(std::forward(y)) { }
as per 20.3.2 (6-8).
So, is this safe? Helpfully, std::pair
is defined in some detail, including memory layout. In particular, it states that
T1 first;
T2 second;
come in this order, so first
will be initialized before second
. This means that in your particular case, the string will be copied before it is moved away, and you're safe.
However, if you were doing it the other way around:
m.emplace(std::move(A.s), A); // huh?
...then you'd get funny effects.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With