Search code examples
c++vectorpass-by-value

How Do Vectors Pass By Value?


If I have created a vector object, an instance that has a size of 24 Bytes (on my machine) will be allocated. I have read that a vector object contains (roughly speaking) two elements:

  1. Pointer points to the first element of the data stored in the heap memory.
  2. The size of the data.

I know that passing by value will not affect the original data, let's say that we have passed (by value) a vector of characters to a function, and the above two elements will be copied (the pointer and the size), so the copied pointer (in the copied vector object) will still point to the same data that the original pointers (in the original vector object) point to.

my question is if the copied pointer still points to the same data (please correct me if I am wrong) why does change the copied vector data doesn't affect the original vector (both vectors are copied and so are the pointers inside them)?

Illustrating my thought

#include <iostream>
#include <vector>

using namespace std;

void printVector(vector<char> vec) {
    for (char c: vec) 
        cout << c << " ";
    cout << endl;
}

void changeVector(vector<char> copiedVector) {
    copiedVector.at(0) = 'x';
    copiedVector.at(1) = 'y';
    copiedVector.at(2) = 'z';
    
    printVector(copiedVector);
}

int main() {
    vector<char> originalVector {'a', 'b', 'c'};
    
    cout << "The original vector contains: ";
    printVector(originalVector);
    cout << endl;
    
    cout << "The copied vector contains: ";
    changeVector(originalVector);
    cout << endl;
    
    cout << "The original vector (after calling changeVector function) contains: ";
    printVector(originalVector);
    cout << endl;

    return 0;
}

The Output:

The original vector contains: a b c

The copied vector contains: x y z

The original vector (after calling changeVector function) contains: a b c

Sorry for posting stupid questions, I tried to do a lot of searching but I didn't get the answers that I was looking for.

I am new to C++, so please be gentle and explain this to me in a simple and detailed way so I can correct myself.

Thanks in advance.


Solution

  • When we say that an object is copied in C++, we do not mean that the bytes of the storage that the object occupies are simply copied as if by memcpy which is what you are describing.

    Instead copying means invoking the copy constructor (or the copy assignment operator) of the class type to perform the copy operation in a way that makes sense for the type. The copy constructor of std::vector performs a deep copy, allocating new memory to store copies of each element of the original vector and the internal pointer of the new vector will be set to point to this newly allocated memory.

    In the call changeVector(originalVector); the argument is an lvalue of type std::vector<char> and the parameter of the function is a (non-reference) std::vector<char>. When the function is called the parameter is copy-initialized from the argument. Because std::vector<char> is a class type that means the compiler will look for a (non-explicit) constructor in std::vector<char> which accepts exactly one lvalue argument of type non-const std::vector<char>. The copy constructor has the signature

    vector(const vector&)
    

    and is therefore a valid choice for this and will be chosen to construct the std::vector<char> in the parameter.

    (The compiler will also consider conversion functions in the argument's type to initialize the parameter, but that is not relevant here.)