constructors and assignment operators

Could someone check if the constructors and assignment operators are in a right manner?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <iostream>
#include <stdexcept>
using std::cout;

template<typename T>
struct X
{
    T * data;
    int size = 0;
    int reserved = 8;
    X() { data = new T[reserved]; cout << this << " constructor\n"; }

    X( const X & x ) :size(x.size),reserved(x.reserved) {
        cout << this << " copy constructor\n";
        data = new T[reserved];
        for( int i = 0; i < size; ++i ) data[i] = x.data[i];
    }
    X( X && x ) :data(x.data),size(x.size),reserved(x.reserved) {
         cout << this << " move constructor\n";
         x.data = nullptr; x.size = 0; x.reserved = 0;
    }
    ~X() { delete[] data; cout << this << " destructor\n"; }

    X& operator=( const X& other) {
        cout << "copy assignment\n";
        if( this == &other) return *this;
        if( reserved < other.size) {
            delete[] data;
            data = new T[other.size];
            reserved = other.size;
        }
        size = other.size;
        for(int i = 0; i < size; ++i) data[i] = other.data[i];
        return *this;
    }
    X& operator=( X&& other) {
        cout << "move assignment\n";
        data = other.data; reserved = other.reserved; size = other.size;
        other.data = nullptr; other.reserved = 0; other.size = 0;
        return *this;
    }


    T& at(int i) {
         if(i < 0 || i >= size) throw std::out_of_range("out of range");
         return data[i];
    }
    const T& at(int i) const {
        if( i < 0 || i >= size) throw std::out_of_range("out of range");
        return data[i];
    }
    void push_back( T t ) {
        if( size == reserved ) {
            T * tmp = data;
            data = new T[ 2*size ];
            for( int i = 0; i < size; ++i) data[i] = tmp[i];
            delete[] tmp;
        }
        data[size++] = t;
    }
};

X<char> f() {
    X<char> x;
    x.push_back('f');
    cout << "doing something\n";
    return x;
}

int main()
{
   X<char> x1 = f();
   cout << x1.at(0) << '\n';
   x1.push_back('a');
   x1.at(0) = 'b';
   cout << x1.at(0) << '\n';
   X x2 = x1;
   x1 = x2;
   x2 = x1;
   X<char> x3;
   x3 = X<char>{};
}
Last edited on
In function
1
2
3
4
5
6
7
8
9
 void push_back( T t ) {
        if( size == reserved ) {
            T * tmp = data;
            data = new T[ 2*size ];
            for( int i = 0; i < size; ++i) data[i] = tmp[i];
            delete[] tmp;
        }
        data[size++] = t;
    }

you miss assign a new value to reserved

In assignment operator the following instructions ( in order to copy the exact state of object )
1
2
 data = new T[other.size];
 reserved = other.size;

should be change to ( assuming that always reserved > size )
1
2
data = new T[other.reserved];
reserved = other.reserved;
Last edited on
1
2
3
4
5
6
X& operator=(X&& other) {
		cout << "move assignment\n";
		data = other.data; reserved = other.reserved; size = other.size;
		other.data = nullptr; other.reserved = 0; other.size = 0;
		return *this;
	}


You have a memory leak as you are not deleting the memory originally used. You should use

1
2
3
4
5
6
7
X& operator=(X&& other) {
		cout << "move assignment\n";
                swap(data, other.data);
                swap(reserved, other.reserved):
                swap(size, other.size);
		return *this;
	}


when the temp (rvalue) object is now destroyed, it will free the memory originally used.
Topic archived. No new replies allowed.