Suppose I have a vector:
std::vector<uint64_t> foo;
foo.push_back(1);
foo.push_back(27);
I pass this vector to a function by reference.
calculate_something(foo);
int calculate_something(std::vector<uint64_t>& vec) {
// ...
}
In rare circumstances, the function needs to locally modify the vector, in which case a copy must be made. Is this the correct way to do that?
if (some_condition) {
vec = vec;
}
vec.push_back(7);
Edit: The reason I am self-assigning is because assigning to another variable results in a copy and my intuition tells me that the same would occur when assigning back to the same variable.
No, it is not correct.
Assignment in C++ doesn't create new objects or change what object a reference refers to. Assignment only changes the value of the object to which the left-hand side refers (either through a built-in assignment operator or through the conventional behavior of operator=
overloads).
In order to create new objects that persist longer than the evaluation of an expression, you need a declaration of some variable. Such a declaration can have an initializer using =
which is often confused for assignment, which it is not:
std::vector<uint64_t> vec2 = vec;
This creates a new object vec2
of type std::vector<uint64_t>
and initializes it with vec
, which implies copying vec
's state into vec2
. This is not assignment! If you write instead
vec2 = vec;
then you have assignment which modifies the state of the object named vec2
to be equal to that of the object referred to by vec
. But in order to do that there has to be already a declaration for vec2
in which the vector object itself has been created. The assignment is not creating a new object.
If you simply use
vec = vec;
then there is only one object, the one that vec
refers to. It is non-obvious whether this assignment is allowed at all, but even in the best case all it could do is copy the state of the object that vec
refers to into the object that vec
refers to, meaning that at the end the state of vec
should simply be unchanged and there is no other side effect.
In general you can't rebind a name or a reference in C++ to a new object.
So what you want is
std::vector<uint64_t> local_vec = vec;
and then you can use local_vec
as a local copy of vec
. You can avoid having to specify the type by using auto
to indicate that you want the variable to have the same type as the right-hand side (minus reference and const
qualifiers):
auto local_vec = vec;