push_back()

I am having trouble writing the push_back() function. I am not sure how to assign the value parameter to the last or new space in the vector.

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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
#// SimpleVector class template
#ifndef SIMPLEVECTOR_H
#define SIMPLEVECTOR_H
#include <iostream>
#include <new>       // Needed for bad_alloc exception
#include <cstdlib>   // Needed for the exit function
using namespace std;

template <class T>
class SimpleVector
{
private:
	T *aptr;          // To point to the allocated array
	int arraySize;    // Number of elements in the array
	void memError();  // Handles memory allocation errors
	void subError();  // Handles subscripts out of range

public:
	// Default constructor
	SimpleVector()
	{
		aptr = 0; arraySize = 0;
	}

	// Constructor declaration
	SimpleVector(int);

	// Copy constructor declaration
	SimpleVector(const SimpleVector &);

	// Destructor declaration
	~SimpleVector();

	// Accessor to return the array size
	int size() const
	{
		return arraySize;
	}

	// Accessor to return a specific element
	T getElementAt(int position);

	// Overloaded [] operator declaration
	T &operator[](const int &);

	// new functions
	void push_back(T);	// New push_back member
	T pop_back();		// New pop_back member
};

//***********************************************************
// Constructor for SimpleVector class. Sets the size of the *
// array and allocates memory for it.                       *
//***********************************************************

template <class T>
SimpleVector<T>::SimpleVector(int s)
{
	arraySize = s;
	// Allocate memory for the array.
	try
	{
		aptr = new T[s];
	}
	catch (bad_alloc)
	{
		memError();
	}

	// Initialize the array.
	for (int count = 0; count < arraySize; count++)
		*(aptr + count) = 0;
}

//*******************************************
// Copy Constructor for SimpleVector class. *
//*******************************************

template <class T>
SimpleVector<T>::SimpleVector(const SimpleVector &obj)
{
	// Copy the array size.
	arraySize = obj.arraySize;

	// Allocate memory for the array.
	aptr = new T[arraySize];
	if (aptr == 0)
		memError();

	// Copy the elements of obj's array.
	for (int count = 0; count < arraySize; count++)
		*(aptr + count) = *(obj.aptr + count);
}

//**************************************
// Destructor for SimpleVector class.  *
//**************************************

template <class T>
SimpleVector<T>::~SimpleVector()
{
	if (arraySize > 0)
		delete[] aptr;
}

//*******************************************************
// memError function. Displays an error message and     *
// terminates the program when memory allocation fails. *
//*******************************************************

template <class T>
void SimpleVector<T>::memError()
{
	cout << "ERROR:Cannot allocate memory.\n";
	exit(EXIT_FAILURE);
}

//***********************************************************
// subError function. Displays an error message and         *
// terminates the program when a subscript is out of range. *
//***********************************************************

template <class T>
void SimpleVector<T>::subError()
{
	cout << "ERROR: Subscript out of range.\n";
	exit(EXIT_FAILURE);
}

//*******************************************************
// getElementAt function. The argument is a subscript.  *
// This function returns the value stored at the sub-   *
// cript in the array.                                  *
//*******************************************************

template <class T>
T SimpleVector<T>::getElementAt(int sub)
{
	if (sub < 0 || sub >= arraySize)
		subError();
	return aptr[sub];
}

//*******************************************************
// Overloaded [] operator. The argument is a subscript. *
// This function returns a reference to the element     *
// in the array indexed by the subscript.               *
//*******************************************************

template <class T>
T &SimpleVector<T>::operator[](const int &sub)
{
	if (sub < 0 || sub >= arraySize)
		subError();
	return aptr[sub];
}

// new functions

//***********************************************************
// The push_back function pushes its argument onto the back *
// of the vector.                                           *
//***********************************************************
template <class T>
void SimpleVector<T>::push_back(T)
{

	
	// Allocate a new array 1 element larger than the current one.
	new temp = new T[arraySize + 1];
	// Copy the current array contents to the new array
	for (int index = 0; index < arraySize; index++)
	{
		temp[index] = aptr[index];
	}

	// Copy the argument value to the end of the array
	temp[arraySize-1] = T;

	// Delete the old array (aptr)
	delete[] aptr;

	// Make aptr point to the new array
	aptr = temp;

	// Adjust arraySize to reflect the extra element you just added
	arraySize++;

	
}
//***********************************************************
// The pop_back function removes the last element           *
// of the vector. It also returns that value.               *
//***********************************************************
template <class T>
T SimpleVector<T>::pop_back()
{
    if(arraySize == 0 || aptr == NULL)
    {
        std::cout<<"cannot pop back! \n";
        return;
    }
    Type* temp = new Type[arraySize];
    for(int index = 0; index < arraySize; index++)
    {
        temp[index] = aptr[index];
    }
    temp[arraySize--];
    delete [] aptr;
    aptr = temp;
}
// Save the last value in the array


// Allocate a new array 1 element smaller than the current one.


// Copy the current array contents (except the last element)
// to the new array


// Delete the old array (aptr)


// Make aptr point to the new array


// Adjust arraySize to reflect the extra element you just removed


// return the last value of the old array


#endif 
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
template <class T>
void SimpleVector<T>::push_back(T t)
{
	// Allocate a new array 1 element larger than the current one.
	T *temp = new T[arraySize++];
	// Copy the current array contents to the new array
	for (int index = 0; index < arraySize; index++)
	{
		temp[index] = aptr[index];
	}

	// Copy the argument value to the end of the array
	temp[arraySize++] = t;

	// Delete the old array (aptr)
	delete[] aptr;

	// Make aptr point to the new array
	aptr = temp;

	// Adjust arraySize to reflect the extra element you just added
	arraySize++;

	
}
//***********************************************************
// The pop_back function removes the last element           *
// of the vector. It also returns that value.               *
//***********************************************************
template <class T>
T SimpleVector<T>::pop_back()
{
	//if (arraySize == 0 || aptr == NULL)
	//{
	//	std::cout << "cannot pop back! \n";
	//	return;
	//}
	//T* temp = new T[arraySize];
	//for (int index = 0; index < arraySize; index++)
	//{
	//	temp[index] = aptr[index];
	//}
	//temp[arraySize--];
	//delete[] aptr;
	//aptr = temp;

	// Save the last value in the array
	T temp = aptr[arraySize - 1];

	// Allocate a new array 1 element smaller than the current one.
	T* temp2 = new T[arraySize - 1];

	// Copy the current array contents (except the last element)
	// to the new array
	for (int i = 0; i < arraySize - 1; i++)
	{
		temp2[i] = aptr[i];
	}

	// Delete the old array (aptr)
	delete[] aptr;

	// Make aptr point to the new array
	aptr = temp2;

	// Adjust arraySize to reflect the extra element you just removed
	arraySize = arraySize - 1;

	// return the last value of the old array
	return temp;
}
#endif  

THis is what i came up with so far. I am getting an extra value at the end after the push_back(int) is executed in main. not sure why
1
2
// Allocate a new array 1 element larger than the current one.
	T *temp = new T[arraySize++];


1
2
// Copy the argument value to the end of the array
	temp[arraySize++] = t;


I wouldn't trust this...

Take a look here - the following code on my machine results in me accessing out-of-bounds memory:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int main() {

	int size = 2;

	int* ptr = new int[size++] {0};//array with three elements, right?

	for (int i = 0; i < size; ++i) {
		std::cout << "ptr[" << i << "]: " << ptr[i] << std::endl;
	}

	delete[] ptr;
	ptr = nullptr;

	std::cin.ignore();
	return 0;
}
ptr[0]: 0
ptr[1]: 0
ptr[2]: -33686019


The reason for this is because the postfix operator (in my case 'size++', in your case 'arraySize++') only increments the parameter after the expression has already taken the original value of 'size' or 'arraySize'.

This can be fixed with the prefix alternative:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>

int main() {

	int size = 2;

	int* ptr = new int[++size] {0};//There we go

	for (int i = 0; i < size; ++i) {
		std::cout << "ptr[" << i << "]: " << ptr[i] << std::endl;
	}

	delete[] ptr;
	ptr = nullptr;

	std::cin.ignore();
	return 0;
}
ptr[0]: 0
ptr[1]: 0
ptr[2]: 0


I doubt this is the cause for your additional undesired element at the end of your vector - I haven't really taken a close look - this just stuck out to me.
Last edited on
I think i was wrong in saying an additional element. It is probably an access to out of bounds memory as you said. However, I have tried the prefix alternative and I get heap error. I have never seen this so I will research this now.
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
template <class T>
void SimpleVector<T>::push_back(T t)
{
	
	// Allocate a new array 1 element larger than the current one.
	T* temp;
	temp = new T[++arraySize];
	arraySize--;
	// Copy the current array contents to the new array
	for (int index = 0; index < arraySize; index++)
	{
		temp[index] = aptr[index];
	}

	// Copy the argument value to the end of the array
	temp[arraySize++] = t;

	// Delete the old array (aptr)
	delete[] aptr;

	// Make aptr point to the new array
	aptr = temp;

	// Adjust arraySize to reflect the extra element you just added
	arraySize;

	
}


This is what i came up with. I know its not the best solution but its the only way I could get the thing to run.
Topic archived. No new replies allowed.