I was introduced to pointers, I quite get it. but I don't know how to store variables in the vector class using pointers.
Here is what I got from my understanding but how should I complete it?
class Vector{
int size;
int* element;
public:
vector(int x);
int size() const { return size }
};
first, you need to define a value that stores the current size - (number of elements inside the vector) - to be able to add values at the end of the vector.
int curr_vec_size;
also, the actual size of the vector should be saved in a variable to check every time you add a value that allocated memory is not full
int memory_size;
second, you need to allocate memory dynamically by using "new" in the constructor
vector(int size)
{
element = new int[size]; //allocating memory (array of integers)
memory_size= size; //size of allocated memory
curr_vec_size= 0; //no values in the vector
}
then you can make a method that takes an int value and adds it to the dynamic array.
void add_value(int passed_val)
{
if(curr_vec_size < memory_size)
{
element[curr_vec_size]=passed_val; //adding the value in the vector
curr_vec_size ++; //because you have added a new value
}
else
cout<<"vector is full \n";
}
Finally, don't forget to delete the memory you've allocated by using destructors that deletes the pointer to this allocated memory.
vector()
{
delete[] element;
}
To complete what you started, you simply need to use new[] operator to allocate memory to store your int values:
vector(int x)
{
size = x;
element = new int[size]; // this allocates an array of int with a size of "size"
}
Then, you can use element[i] to access i's element of your array.
You'll later need (it's a must) to release allocatd memory to prevent memory leak by implementing a destructor:
~vector()
{
delete [] element;
}
Note that you should (must) also also follow at least the rule of 3 to have you vector be copiable.
Related
Via stackoverflow threads like this one, I discovered that you could use an array of pointers to manage a 2D array. In the past I used to use pointer to pointer to store 2D arrays, but now I have a requirement to store my data in contiguous memory, so pointer to pointer format doesn't work anymore.
A raw 2D array is an alternative to array of pointers, but raw 2D array doesn't work for me because I want to be able to allocate storage in the heap and not on the stack because my container can be very large and I might encounter stack overflow if I use vanilla 2D array.
My question is about how memory is allocated for array of pointers. I use new operator like below (see my constructor) to allocate my array of pointers
#include <iostream>
using namespace std;
template<typename DataType, unsigned numRows, unsigned numCols>
class Container2D {
public:
Container2D() {
m_data = new DataType[numRows][numCols];
}
~Container2D() {
delete [] m_data;
}
DataType* getData() { return &m_data[0][0]; }
private:
DataType (*m_data)[numCols];
};
int main() {
Container2D<int, 3, 3> container;
return 0;
}
Does new DataType[numRows][numCols] allocate the entire 2D array on the heap or does it allocate numRows pointers on the heap while allocating numCols objects of type DataType on the stack?
In a pointer to pointer scenario (where I'd define my storage as DataType** m_data), I know for a fact that both dimensions of my array are allocated on the heap and I would call delete m_data[i] for each column and then call delete[] m_data to free my row data. In the array of pointers scenario, I'm not sure if my destructor above is freeing up data correctly.
One way is to use a 1D contiguous array and implement the 2D index to 1D index mapping instead:
#include <iostream>
#include <cassert>
using namespace std;
template<typename DataType, unsigned numRows, unsigned numCols>
class Container2D {
public:
Container2D() { m_data = new DataType[numRows * numCols]; }
~Container2D() { delete [] m_data; }
inline DataType operator()(unsigned i, unsigned j) const {
assert( 0 <= i && i < numRows);
assert( 0 <= j && j < numCols);
return m_data[i*numCols+j];
}
inline DataType& operator()(unsigned i, unsigned j) {
// same as above, but this allows inplace modifications
assert( 0 <= i && i < numRows);
assert( 0 <= j && j < numCols);
return m_data[i*numCols+j];
}
private:
DataType* m_data;
};
int main() {
Container2D<int, 3, 3> container;
int x = container(0,0); // retrieve the element at (0,0);
container(1,2) = 9; // modify the element at (1,2);
// int y = container(3,0); // triggers assertion errors for out-of-bound indexing
return 0;
}
Notes:
If numRows and numCols do not change for a specific class instance, new and delete are not necessary in this case. If they do dynamically change, it is better to store them as member variables instead of template parameters. If numRows and numCols are too large, one can dynamically allocate Container2D objects as a whole.
As #GoswinvonBrederlow commented, there is no difference between this and new m_data[numRows][numCols] in terms of memory layout, but this convention makes it easier to extend to higher dimensions.
Does new DataType[numRows][numCols] allocate the entire 2D array on the heap or does it allocate numRows pointers on the heap while allocating numCols objects of type DataType on the stack?
When you write
DataType arr[numRows][numCols];
the memory will be in one contiguos block as you mentioned. Nothing changes there when you use new. It will allocate one contiguos block of memory of the specified type. There is no hidden array of pointers into the real data.
I am currently learning basics of c++, and am coming across an issue with the class array below.
class Arrayclass {
private:
int arraySize;
float array[];
public:
Arrayclass(int arraySize) {
float * array = new float[arraySize]();
}
~Arrayclass() {
delete[] array;
}
}
As far as I am aware, I am having issues with the array being initialized in the constructor not actually corresponding to a stored array in the new class, thus when I am initializing a new class in my main, the array created holds 0 values. I apologize my explanation is unclear, just trying to understand how the array initialized in the constructor correlates to the array in my private.
float array[]
either is an extension or just doesn't compile. For a C-style static array, Type name[constexpr_size] is used. For a dynamic array, Type* name is stored as a pointer to the beginning of the storage allocated.
Dynamic Array
OK, we need the second option. Then, we start with your snippet
class Array { // "class Arrayclass" -> "class Array", no need to repeat ourselves
private:
float* array{};
int size{}; // "Array::arraySize" -> "Array::size", again
public:
~Array() { delete[] array; } // your destructor is fine
};
(see member initializer as an explanation to those {} initializers in float* array{} and int size{}).
What about
Arrayclass(int arraySize) { float * array = new float[arraySize](); }
, you create a local float* which dies at the end of scope (=the constructor). You probably meant to store that newly allocated array in (this->)array:
Array(int newSize) { // BAD CODE, see below
array = new float[newSize]{};
size = newSize;
}
but the code above is like writing float* p; p = something (create default, than initialize it) instead of float* p{something} (initialize on creation), let's improve it by using member initializer list:
Array(int newSize): array{new float[newSize]{}}, size{newSize} {}
Now, your array (almost) can construct and destruct properly.
==========
However, there's still an issue left: code such as
{
Array a1{42};
Array a2{a1}; // copy construction
}
has undefined behavior and in practice (in this case) should/might crash your application. Why? Because it works as something like (sizes omitted):
{
float* array1{new float[42]{}};
float* array2{array1};
delete[] array1;
delete[] array2; // that UB (double free); the same dynamic array is deleted twice
}
Well, it is a topic for another "lesson". See the rule of three (five) (zero). In general, see RAII and copy/move-semantics.
I am running into a memory leak problem when allocating a 2D array.
But I could not understand why the memory leaks.
My reasoning is that at Note A, I have already freed allocated memory, since data_[0] == data_, why do I have to do the free at Note B?
class Matrix {
public:
Matrix(int r, int c) {
this->rows = r;
this->cols = c;
data_ = new int*[r];
for (int i = 0; i < r; i++) {
data_[i] = new int[c];
}
}
~Matrix() {
for (int i = 0; i < this->rows; i++) {
delete [] data_[i]; // Note A;
}
delete[] data_; // Note B; <-- not doing this line will leak memory, but why?
}
private:
int rows;
int cols;
int **data_;
};
What you post there isn't really a 2D array, it's a 1D array-of-pointers (data_), and then you allocate a separate array-of-ints for each element of the first array (so data_[0] is an array of c ints, data_[1] is an array of c ints, and so on).
Given that, it's natural that you'll have to do one delete[] in your destructor for each new that you performed earlier in your constructor.
A graphical diagram of your memory allocations and how they point to each other might look like this (if c==6 and you have set all of your arrays' integers to 0):
A real 2D array allocation would look like this: int * array2D = new int[6][8];, but of course C++ only supports 2D arrays if the array-dimenions are compile-time constants, so that probably wouldn't solve the problem your Matrix class is meant to solve.
When you have created 2D array (for example 3x3), you have created 1 array with 3 elements, where each element is pointer to separate array. So to clear memory for this matrix you need to clear 4 arrays (3 rows and 1 array containing pointers).
You can check how many times in your code you are calling new operator
it will be r+1 times
data_ = new int*[r];// 1 time
for (int i = 0; i < r; i++ {
data_[i] = new T[c]; // r times
}
Part I:
The line data_ = new int*[r]; allocates and default initializes a dynamic array of int* through new, so you would need to provide a corresponding delete [] data_; for this line.
Part II:
The line data_[i] = new int[c]; dynamically allocates and default initializes an int array and then the pointer to that first element is returned and stored as the data_[i] element. So here again you would need a corresponding delete [] data_[i]; to get rid of the memory leak.
So these were the reasons why you need two separate delete []. The process is as shown in the screenshot. Also note that the important thing is the default initialization. So the int array elements will not all have a value 0 as wrongly shown in the answer by #Jeremy Friesner.
My professor wrote the following code:
template <class T>
Set<T>& Set<T>::operator=(const Set<T>& set) {
if (this == &set) return *this;
T* data_temp = new T[set.size];
try {
for (int i = 0; i < size; ++i) {
temp_data[i] = set.data[i];
}
} catch (...) {
delete[] temp_data;
throw;
}
delete[] data;
data = temp_data;
size = maxSize = set.size;
return *this;
}
And he pointed that temp_data[i] = set.data[I]; calls operator=, and I am wondering why this doesn't leak memory?
For example if operator= failed in the 4th loop then we are deleting temp_data, but what about the values of the first 3 cells in temp_data which were allocated inside operator= code? we aren't freeing them.
For example if operator= failed in the 4th loop then we are deleting temp_data, but what about the values of the first 3 cells in temp_data which were allocated inside operator= code? we aren't freeing them.
new[] allocates the entire array and constructs all of the T objects in it, before the loop is reached. delete[] destructs all of the objects in the array, and deallocates the entire array. So, it is the responsibility of T's constructor and destructor to initialize and finalize T's data members properly.
The loop merely updates the content of the data members of the objects in the array. It is the responsibility of T::operator= to copy and free T's data members properly as needed.
There is no leak in this Set::operator= code. However there is a minor mistake - the loop needs to use set.size instead of size.
for (int i = 0; i < set.size; ++i)
The new array is allocated to set.size number of elements, so that is how many elements the loop needs to copy.
Using size for the loop, if the Set being assigned to is smaller than the Set being copied, the new array won't copy all of the elements. And if assigning to a Set that is larger, the loop will go out of bounds of both arrays.
If you are experiencing a leak, it would have to be in either T::operator= or in T::~T(), neither of which you have shown. Assuming Set::Set() and Set::~Set() are initializing and freeing data properly, this is.
Lets remove some complications from this code. Lets assume T == int and instead of storing many ints we only store one:
int_store& int_store::operator=(const int_store& set)
{
int* temp_data = new int; (1) allocate
try
{
*temp_data = *set.data; (2) assign
}
catch (...)
{
delete temp_data; (3) free temp
throw;
}
delete data; (4) free old
data = temp_data;
}
The method has one allocation int* temp_data = new int (1). It the tries to assign the other sets data to that temp value (2). When this fails the temp has to be deleted (3) otherwise we can replace the old data with the new data stored in temp_data and before doing that we have to delete the old data (4).
There is no allocation in the try block. All memory allocated in the function is either deleted (when assignment fails) or it is used to replace the old data, in which case the old data is deleted before.
If data is an array instead of a single int (almost) nothing changes and there is no leak. The elements you worry about are already allocated in the line T* data_temp = new T[set.size]; and then delete[] temp_data; will delete all of them.
I have been trying to make a infinite size stack using pointer to any int:
//in class:
int* stack;
//In constructor:
stack = new int();
//In deconstructor:
delete stack;
//In Push:
stack(++top) = element;
Is this declaration correct? Can I use this to make an infinite size stack? I run into error when I try to put elements into the stack using such pointer declaration.
It seems you are writing codes in C++? If no, please just ignore my post(face palm).
Firstly, the memory that could be assigned to a program is limited, i.e. no infinite size stack. In C++, there is BSS, Stack and Heap memory. In your case, you have used new operator to assign memory. This in fact effectively means you would like to get a piece of memory in the heap to store your value. Though the size of heap could be dynamically extended, its memory size is still not infinite.
Moreover, it seems what you would like to do in the constructor is to build up an int array with unlimited size. In fact, to declare an array, you may write new int[arraySize] to declare an int array of size, arraySize, in the heap. However, what you have written here is allocating a single int in the heap since the brackets you used are not square, but round. Unfortunately, to create an array, you need to declare its size first (for more details, you may search for stack array and dynamic array). So as to get rid of the size problem, you may use other data structures like std::vector and so forth for simple.
int* stack;
stack = new int();
These 2 statements are to have a pointer pointing to a single int stored in heap memory. Therefore, currently, the stack you make seems to be only able to store an int only.
As for the push function, top is the index of the top int in the stack?
One more thing, in case, what you want to make is creating a pointer to point an int array, and use the array as a stack. Then, you may think about the way to add memory, and have the deconstructor revised to be like this:
delete[] stack;
If you find difficulty in understanding my above paragraphs and have interest in learning more, perhaps you may firstly learn about stack & heap, then, the array declaration as well as its relationship with the memory allocation, followed by the knowledge about pointers.
I am a newbie. Hopefully, I haven't made any mistake in my answer.
First of all new int () creates only a single int not an array of integers therefore you can't do something like stack(++top) = element;.
If you want to create a dynamic array you should use int* stack = new int[size] and delete it with delete [] stack. As you can see the array has a limited size of size but you can resize it when it becomes full. There is no built-in way to resize the array but you can create a new dynamic array with bigger size and copy the old array into it and then remove the old array. But again the stack won't have infinite size since your memory is limited. If the allocation fails an exception will be thrown.
Below is a simple implementation of stack based on a dynamic array.
#include <stdexcept>
using namespace std;
class Stack{
public:
Stack (int _size = 20){
size = _size;
topIndex = 0;
stack = new int [size];
}
~Stack (){
delete [] stack;
}
void resize(){
int new_size = size*2;
int * new_stack;
// try{
new_stack = new int[new_size];
// } catch (std::bad_alloc&) {
// unsuccessful allocation
// }
for ( int i=0; i<size; ++i ){
new_stack[i] = stack[i];
}
delete [] stack;
stack = new_stack;
size = new_size;
}
void push(int element){
if (topIndex + 1 == size){
resize();
}
stack[topIndex++] = element;
}
int top(){
if ( topIndex <= 0 ){
throw std::out_of_range("stack is empty");
} else {
return stack[topIndex-1];
}
}
void pop(){
if ( topIndex <= 0 ){
throw std::out_of_range("stack is empty");
} else {
--topIndex;
}
}
private:
int * stack;
int size;
int topIndex;
};
int main(){
Stack stk;
for ( int i=0;i<50;++i ){
stk.push(i);
cout << stk.top() << endl;
}
for ( int i=0;i<50;++i ){
stk.pop();
cout << stk.top() << endl;
}
}
Note that this is all just for practice and the above implementation is error prone. You should almost always use built-in data structures in practical situations.