Suppose there is a copy--and-move-constructible (and assignable) object, such as std::vector<int>
. A class of mine will accept on such object and store it as a member:
class A
{
public:
void SetVector(const std::vector<int>& v) { v_ = v; }
private:
std::vector<int> v_;
};
This will make a copy of the vector given by the user. This is classical C++ approach to pass arguments to a function)
Now, suppose the user would be happy with moving his/her vector into an object of type A
. This will avoid a copy. For that we need a member function that takes an r-value reference:
class A
{
public:
void SetVector(const std::vector<int>& v) { v_ = v; }
void SetVector(std::vector<int>&& v) { v_ = std::move(v); }
private:
std::vector<int> v_;
};
Now the user has the choice: the vector can be copied into the object, or moved, in which case the original vector is reset (on in whatever state the moved object is after being moved).
On the other hand, we had to write two separate member functions to give the user this choice. When we have tons of similar functions, the burden can be problematic.
There seems to be a third possibility:
class A
{
public:
void SetVector(std::vector<int> v) { v_ = std::move(v); }
private:
std::vector<int> v_;
};
This way, the user can provide the vector by l-value reference, in which case the vector is copied, or by r-value reference, in which case it is moved.
Are there drawbacks to this strategy?
Is there perhaps some corner case I'm not considering?
The only difference I see is that with the third way (pass by value) there is always one more move operation (either a copy and a move or two moves). I suppose there is not much the compiler can do to optimize one move away. Assuming I'm happy to pay the price of a move in order to have just one version of the function, is this pass-by-value approach a good idea?
Aucun commentaire:
Enregistrer un commentaire