Search code examples
c++dynamic-memory-allocation

C++: vector implementation and dynamic memory allocation


I was looking to understand how vector is implemented in C++. There was a previous question that asked this, and so I took a look at it, and I have a small question. Assuming the implementation in the linked question is correct, let's look at this code:

int main(){
    Vector<int> test2 = test_Vector();
    cout << test2[0] << endl;
    return 0;
}


// below is NOT the STL vector object, but the one in the linked question,
// in which the asker tries to implement STL vector himself/herself 
Vector<int> test_Vector(){
    Vector<int> test;
    test.push_back(5);
    return test;
}

As I understand it, the test Vector object is created locally, so when the test_Vector method returns, the local object goes out of scope, thereby calling the destructor and delete-ing the dynamic array. Since the code actually works and 5 is printed, I guess I'm wrong. What's the right explanation?


Solution

  • You are right, but you're missing one important thing.

    Because you're returning a Vector<int>, you should think of it as being copied. This would normally invoke the copy constructor, which copies test into a new instance of Vector<int>. The copy constructor is implemented in the linked question as:

    template<class T>
    Vector<T>::Vector(const Vector<T> & v)
    {
        my_size = v.my_size;
        my_capacity = v.my_capacity;
        buffer = new T[my_size];  
        for (int i = 0; i < my_size; i++)
            buffer[i] = v.buffer[i];  
    }
    

    Note that the copy constructor might not be invoked due to Return Value Optimization (see hair-splitting in comments below). Compilers are allowed to optimize the copy away in many cases, and the C++ standard allows for the fact that this optimization may change program behaviour.

    Whether the object is copied, or RVO is applied, you should end up with the same thing. The optimization should not ruin your object provided you follow normal object-oriented practices.

    You should always think of function return values being passed by value (ie copied) regardless of type, and then consider that your compiler is probably doing RVO. It's important not to forget the Rule of Three (or Four, or Five).