Home > Net >  Does assigning a vector variable to itself result in copy C
Does assigning a vector variable to itself result in copy C

Time:09-01

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.

CodePudding user response:

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;

CodePudding user response:

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 you need a copy vec = vec does not help. No matter if = skips selfassignement, after that line vec still refers to the parameter that the caller passed to the function.

If the function needs a copy rather than a reference, pass the vector by value:

int calculate_something(std::vector<uint64_t> vec) {
    // ...
}

If you need both, a reference and a copy then pass by reference and make a copy:

int calculate_something(std::vector<uint64_t>& vec) {
    auto copy = vec;
    // ...
}

CodePudding user response:

Additionally as to what others have said, copy assignment operators in C are typically (but not mandatory) implemented as below:

SomeClass& operator=(const SomeClass& other)
{
    if (this != &other)
    {
        // copy the properties of other to this
    }

    return *this;
}

So a self-assignment has no effect.

  • Related