Dynamic allocation copy constructor

Hi, I am learning Class and I want to write a code that insert value into an array that have been allocated dynamically. I want my program to increase memory allocation of the array by *2 if the current size of the array is full, and also copy the precedent value of the array into the bigger one. (I want to do this manually and not use vector).

Here is the code I wrote, respecting rule of 3. All is working but when I create the function alias my program doesn't work anymore. I spend lot of time to try different possibility, but don't find something that work. Can you explain why, and how can I correct code.

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
Data::Data() : _database(nullptr) 
{
    this->_database = new int[2];//Default value = 2
    this->_currentSize = 0;
    this->_size = 2;
}
Data::Data(int size): _database(nullptr)
{
    this->_database = new int[size];
    this->_size = size;
    this->_currentSize = 0;
}
Data::Data(const Data& init)
{
    if (this->_database != nullptr)
    {
        int* tmp = new int[init._size];
        for (int i = 0; i < this->_currentSize; i++)
            *(tmp + i) = *(init._database + i);

        delete[] this->_database;

        this->_database = tmp;
        this->_size = init._size;
        this->_currentSize = init._currentSize;
    }
}

Data::~Data()
{
    if (this->_database)
    {
        delete[] this->_database;
    }
        
}

void Data::display()
{
    cout << "Size: " << this->_size << endl;
    cout << "Current size: " << this->_currentSize << endl;
    cout << "Values:";
    for (int i = 0; i < this->_currentSize; i++)
        cout << *(this->_database + i) << " ";
    cout << endl;
}
void Data::add(int value)
{
    if (this->_currentSize < this->_size || this->_currentSize > this->_size)
    {
        *(this->_database + _currentSize) = value;
    }
    else
    {
        int* tmp = new int[this->_currentSize*2];

        for (int i = 0; i < this->_currentSize; i++)
            *(tmp + i) = *(this->_database + i);

        *(tmp + this->_currentSize) = value;

        delete[] this->_database;
        this->_database = tmp;
   
        this->_size = this->_currentSize*2;
    }
    this->_currentSize++;
}

void Data::alias(Data source)
{
    int* tmp = new int[source._size];
    for (int i = 0; i < source._currentSize; i++)
        *(tmp + i) = *(source._database + i);

    this->_database = tmp;
    this->_currentSize = source._currentSize;
    this->_size = source._size;
}


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Data
{
private:
    int* _database;
    int _size;
    int _currentSize;
public:
    Data();
    Data(int size);
    Data(const Data& init);
    ~Data();

    void display();
    void add(int value);
    void alias(Data source);
};


1
2
3
4
5
6
7
8
9
int main()
{
    Data one(2), second;
    for (int i = 0; i < 10; i++)
        one.add(i);
    second.alias(one);
    one.display();
	return 0;
}

Last edited on
what does not work? can you describe the error message or issue?

alias leaks memory badly, by the way. it throws away this->database which may have had memory.
Can you explain more why alias is not allocating memory correctly
As @jonnin hinted, line 76 assigns this->database. However, any previous value of this->database gets leaked.

Another thing... why do you have an initialization list for _database and then immediately overwrite it in the first line of your constructor (first 2 constructors). Either put all 3 lines into the initialization list, or put all 3 into the body. The initialization list is probably better.

In the 3rd constructor--your copy constructor--you know that this->database is not valid because you are constructing this object. There is no need to check for null. And it's a constructor, so there is no need to delete the old this->database (line 21). That's only needed for an assignment operator (which is what alias essentially is).

And why are you creating tmp in either place? Just delete (if necessary) and set this->database = new int[size];

One more thing: in your second constructor, what do you do if the argument is 0?

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
 int* tmp = new int[source._size];  //ok, get a temp variable and all that looks fine. 

    for (int i = 0; i < source._currentSize; i++)  
//tmp is sized off source.size but iterates off currensize. is that messed up? could be right, i got
// no idea, but its not what you allocated. 

        *(tmp + i) = *(source._database + i); //why do this to the reader?  how about tmp[i] = source.database[i]; ?!   

    this->_database = tmp;   //old database memory, if any, is thrown away and leaked. 
    this->_currentSize = source._currentSize;  //ok, now they match.  but size vs currentsize is still confused above. 
    this->_size = source._size; //ok
Last edited on
Consider:

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
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <algorithm>

class Data {
private:
	int* _database {};
	size_t _size {};
	size_t _currentSize {};

public:
	Data();
	Data(size_t size);
	Data(const Data& init);
	~Data();

	void display();
	void add(int value);
	void alias(const Data& source);
};

Data::Data() : _database(new int[2]), _size(2) {}

Data::Data(size_t size) : _database(new int[size]), _size(size) {}

Data::Data(const Data& init) : _database(new int[init._size]), _size(init._size), _currentSize(init._currentSize)
{
	std::copy_n(init._database, init._currentSize, _database);
}

Data::~Data()
{
	delete[] _database;
}

void Data::display()
{
	std::cout << "\nSize: " << _size;
	std::cout << "\nCurrent size: " << _currentSize;
	std::cout << "\nValues: ";

	for (int i = 0; i < _currentSize; ++i)
		std::cout << _database[i] << " ";

	std::cout << '\n';
}

void Data::add(int value)
{
	if (_currentSize < _size)
		_database[_currentSize] = value;
	 else {
		int* tmp {new int[_currentSize * 2]};

		std::copy_n(_database, _currentSize, tmp);
		tmp[_currentSize] = value;
		_size = _currentSize * 2;

		delete[] _database;
		_database = tmp;
	}

	++_currentSize;
}

void Data::alias(const Data& source)
{
	int* tmp {new int[source._size]};

	std::copy_n(source._database, source._currentSize, tmp);
	_currentSize = source._currentSize;
	_size = source._size;

	delete[] _database;
	_database = tmp;
}

int main()
{
	Data one(2), second;

	for (int i = 0; i < 10; ++i)
		one.add(i);

	one.display();

	second.alias(one);
	second.display();

	second.add(20);
	second.display();
}




Size: 16
Current size: 10
Values: 0 1 2 3 4 5 6 7 8 9

Size: 16
Current size: 10
Values: 0 1 2 3 4 5 6 7 8 9

Size: 16
Current size: 11
Values: 0 1 2 3 4 5 6 7 8 9 20

Last edited on
Topic archived. No new replies allowed.