dimanche 26 novembre 2017

Deep copy and assignment overload and std::swap

Actually I have 2 separate problems right now, so Ill divide this question into 2 parts. First one is about deep copy and assigment operator overload

First, my class header

template <class T>
class MyVector{    
    std::unique_ptr<T[]> p_array;
    int p_size; 
    int p_capacity; 
public: 
    MyVector();
    MyVector(const MyVector&);
    MyVector& operator= (const MyVector&);
}

And here are my copy constructor and assignment operator overload function

template <class T>
MyVector<T>::MyVector(const MyVector &source) {
    p_capacity = source.p_capacity;
    p_size = source.p_size;
    p_array = std::make_shared<T[]>(p_capacity);
    for(int i = 0; i < p_capacity; i++) {
        p_array[i] = source.p_array[i];
    }
}

template <class T>
MyVector& MyVector<T>::operator=(const MyVector &source) {
    if(this == &source) return *this;

    p_capacity = source.m_capacity;
    p_size = source.m_size;

    p_array = std::make_unique<T[]>(p_capacity);
    for(int i = 0; i < p_capacity; i++) {
        p_array[i] = source.p_array[i];
    }
}

In main

int main() {
MyVector<int> vecA;
//adding elements to vecA
MyVector<int> vecB(vecA);
}

Unfortunatelly what I got is

g++ -std=gnu++14 -static-libstdc++ -g3 -Icode/include -c code/source/my_vector.cpp -o obj/my_vector.o code/source/my_vector.cpp:20:1: error: invalid use of template-name ‘MyVector’ without an argument list MyVector& MyVector::operator=(const MyVector &source) { ^ Makefile:29: recipe for target 'obj/my_vector.o' failed make: *** [obj/my_vector.o] Error 1

Part 2

In same class I got extendArray() function that if called, extend array capacity by 2 and copy all elements from old array to new. I tried using for loop to iterate through all elements and it works just fine, but I wanted to use std::swap instead and then I came into some strange trouble.

template <class T>
void MyVector<T>::extendArray() {
    p_capacity *= 2;
    std::unique_ptr<T[]> temp_array = std::make_unique<T[]>(p_capacity/2);
    std::swap(p_array, temp_array);
    p_array.reset();
    p_array = std::make_unique<T[]>(p_capacity);
    std::swap(temp_array, p_array);
}

in main I just do this

int main(){
        MyVector<int> test;
        test.pushBack(5);
        test.pushBack(10);
        test.pushBack(15);
        test.pushBack(20);
        test.pushBack(25);     

        for(int i = 0; i < test.getCapacity(); i++) {
            cout << test[i] << ", ";
        }  
    }

I expect to see following output (once 4th element is added, extendArray() function is called and it extends capacity from 4 to 8
5, 10, 15, 20, 25, 0, 0, 0
And I got it when I use my old extendArray() func based on for loops, but if I use one with std::swap I get
5, 10, 15, 20, 25, 0, 1041, 0
I have no idea where this 1041 comes from. What's more, valgrind shows Valgrind shows 9 erros on 4 contexts like that:

==5967== Invalid write of size 4
==5967== at 0x403000: MyVector::pushBack(int const&)
(my_vector.cpp:17)
==5967== by 0x402CE7: main (main.cpp:11)
==5967== Address 0x542bc88 is 0 bytes after a block of size 8 alloc'd
==5967== at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==5967== by 0x404707: operator new(unsigned long) (in /home/maciek/Programming/MyVector/MyVector)
==5967== by 0x403968: operator new[](unsigned long) (in /home/maciek/Programming/MyVector/MyVector)
==5967== by 0x40314B: std::_MakeUniq::__array std::make_unique(unsigned long) (in /home/maciek/Programming/MyVector/MyVector)
==5967== by 0x402F3C: MyVector::MyVector() (my_vector.cpp:6)
==5967== by 0x402C99: main (main.cpp:8)
==5967==

Aucun commentaire:

Enregistrer un commentaire