I have an issue with emplace and try_emplace as they always use the copy constructors when moving an object in.
#include <iostream>
#include <unordered_map>
#include <map>
using namespace std;
class Too {
public:
Too(int x, int y):x_(x), y_(y) {
cout << "init " << x_ << endl;
}
Too(const Too& too):x_(too.x_+1), y_(too.y_+1) {
cout << "Copy happen: x = " << x_ << endl;
}
~Too() {
cout << "delete too " << x_ << endl;
}
private:
int x_, y_;
};
std::map<int, Too> v;
int main()
{
v.emplace(100, Too{ 100,23 });
v.try_emplace(12, 12, 13);
Too t = Too(10, 11);
v.try_emplace(11, std::move(t));
}
output init 100 Copy happen: x = 101 delete too 100 init 12 init 10 Copy happen: x = 11 delete too 10 delete too 101 delete too 12 delete too 11
As you can see, only v.try_emplace(12, 12, 13) do not use the copy constructor. both v.emplace(100, Too{ 100,23 }) and v.try_emplace(11, std::move(t)) invoke the copy constructor.
So how can it be even when I use std::move(t)?
Any suggestion would be highly appreciated.
Thanks,
Since you've provided a copy constructor for your class, the move constructor Too::Too(Too&&)
will not be implicitly generated by the compiler.
Moreover, when there is no move constructor available for a class, the copy constructor can be used.
For using the move constructor you have to explicitly provide an appropriate user-defined move constructor Too::Too(Too&&)
, then you will get the desired result.
You can add the move constructor either by adding Too(Too&&) = default;
or writing your own move constructor which will do the initialization in the constructor initializer list.