How to delete pointers that are elements of an array - c++

Below is the code for constructor and destructor. Destructor successfully destructs the array created by option 1. What if we have multiple array as in option 2. Will the same destructor coding is enough to delete or some changing in the code is required.
#include "iostream"
class Mystack
{
private:
int capacity;
int top[3];
int *input;//option1
int *input[3];//option 2
public:
Mystack();
~Mystack();
void push(int stackNum, int elem);
void pop(int stackNum);
void display();
};
Mystack::Mystack()
{
capacity = 3;
top[3] = { -1 };
input[] = new int[capacity]; //option 1
input[3] = new int[capacity];// option 2
}
Mystack::~Mystack()
{
delete[]input;// Works for option 1. Should it be same for option 2??
}

Your int *input[3] is a raw array that will contain pointers to ints, a.k.a int*. You have a lot of errors in your code, for example you are accessing the 4th position of the array top with top[3], which has just 3 elements, and you are assigning something { -1 } to its imaginary 4th element, instead of an int.
These declarations are also not valid, because you are using the same identifier for 2 different variables:
int *input;//option1
int *input[3];//option 2
If you want to delete the memory allocated by an array of pointers, I would iterate through the array calling each time delete [] on them:
for(int i=0; i<3; i++)
delete [] input[i];
This is going to free all the memory allocated by the pointer to integers input[0], input[1] and input[2].

Related

Is there a solutions to escape from 'invalid conversion int* to int' C++?

I'm getting this error when I try to compile my code.
I dont have any *(pointers) and can't understand why im getting this.
Im working now with template. You can check my code too see:
#include <iostream>
#include <cstdlib>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
template <class T>
class Set
{
public:
T **p;
int n;
Set(){
};
Set(int n)
{
this->n = n;
p = new T*[n];
}
~Set()
{
if(p) delete []p;
}
void setValues(T k,int l)
{
p = k;
n = l;
}
void add(T k)
{
T p1;
p1 = p;
p = new T[n+1];
p = p1;
p[n+1] = k;
n++;
}
void remove(T k)
{
T p1;
int l =0;
p1 = p;
p = new T[n-1];
for(int i=0;i<n;i++)
if(p1[i]!=k)
{
p[l] = p1[i];
l++;
n--;
}
}
void operator+(Set s)
{
for(int i=0;i<n;i++)
p[i]+=s.p[i];
}
void operator-(Set s)
{
for(int i=0;i<n;i++)
p[i]-=s.p[i];
}
void operator*(Set s)
{
for(int i=0;i<n;i++)
p[i]*=s.p[i];
}
void show()
{
for(int i=0;i<n;i++)
cout<<p[i]<<" | ";
}
};
int main()
{
Set<int> s1,s2;
int arr[]={0,2,3,4,3,6};
int n=6;
float arr2[]={0.5,12.1,1.7,23.15};
char arr3[]={'a','h','m','k','c','e'};
s1.setValues(arr,n); // <------------- here is error;
s1.show();
}
I'm getting error on this line s1.setValues(arr,n);
This is setValues() method:
void setValues(T k,int l)
{
p = k;
n = l;
}
I had tried to avoid the error by using & like that: s1.setValues(arr,&n)
and s1.setValues(arr,*n)
Also I tried to change it in method: void setValues(T k,int &l) and void setValues(T k,int *l)
in class: public:
T **p;
int *n; and public:
T **p;
int &n;
In my first version I have tried to use: s1.setValues(arr,6) where 6 is the length of the array. But I was also getting the error;
Edit: I had misread the type of p, and also apparently read the error backwards.
The class is intantiated with T as int. All arrays decay to pointers, so arr is of type int*. This means you cannot pass it in as the first argument of setValues.
void setValues(T k, int l);
...
s1.setValues(arr, n); //arr is type int*, but k is of type int.
I'm afraid I don't understand what your code is doing well enough to suggest how you might want to fix it, but this is why the compiler is emitting that error.
Preliminary remark: since you do not use std::set I suppose this is an exercise, and that you are not allowed to use std::vector which would considerably facilitate the management of p
The problem(s)
There are some contradictions in this code, and some more errors that do not appear yet because the corresponding template member function is not used:
The member T** p is defined as a pointer to pointer of T
In the constructor you allocate an array of pointers to T, which will give you indeed a pointer to pointers of T.
But in add() and remove() you try to reallocate p's with an array of T, which will give you a T* instead of T**. In addition you clearly want to add or remove a value and not a pointer.
But in set value, it is not clear if you want to set a single value (which the T k in the signature suggests) or if you want to set all the values from an array (which the length argumen int l suggests). Given the name of the function has Values in plural, I will assume the second alternative.
Solution Step 1: Get it to compile. But it won't really work
You need to correct:
T *p;
and adapt the constructor accordingly with p = new T[n];
auto p1 = p;
You then need to change your function definition to:
void setValues(T k[],int l) // option 1
void setValues(T *k,int l) // or option 2
The good news is that the code will then compile
The bad news is that it will not do what you want. Furthermore the code of the function and some other problems will cause UB (meaning that a lot of bad things can happen, including memory corruption, crash, etc...).
Solution Step 2: assignment of arrays, pointers and the rule of 3
This code does not what you expect it to do:
void setValues(T *k, int l)
{
p = k; // OUCH !!!!!! pointer copy and not copy of the array elements
n = l;
}
Currently, you do not copy the elements of an array, but you replace a pointer. This has following consequences:
first you will leak memory, since the pointer to the allocated memory is lost and will never be freed.
second, you will make this pointer point to an array that was not allocated with new[], which might hurt you badly when you later delete[] this pointer.
third: the array to which your class points might get deleted by the owner of the array, in which case you'd use a dangling pointer.
So you need to adapt your code as follows:
void setValues(T k[],int l) // change signature
{
if (n!=l) { // if the size is the same, we'll reuse p, if not:
delete[] p; // avoid the memory to leek
p= new T[l]; // start with a fresh memory
n = l; // define new length
}
for (int i=0; i<l; i++)
p[i]=k[i]; // copy array elements one by one
}
Another important problem is the rule of 3. This is not a problem with your current main() but quickly will become: if you work with pointers in a constructor or a destructor, you should define a copy construtor and an assignement operator. If you don't, you risk to end with shallow copies of your Set (2 different object but using the same pointer).
Solution Step 3: get rid of the remaining issues
First, your default constructor leaves p and n unitialized. They could be random value, which might cause the destructor to try to delete something that was not allocated. And the same for anny other function that assumes that things that assumed the member values would be consistend. So:
Set(){
p=nullptr;
n=0;
};
Then you have similar problems in add(), that you had in setValues() with the pointer assignment. IN addition you go out of bounds, even after the realocation: the last element of an array p with n+1 element is p[n] and not p[n+1]. I let you as an exercise to improve it.
Online demo

Getting length of an array when passed to an object

I am learning about pointers, and how they can be used to send array(size is not assigned) to objects. Ultimately i m trying to learn how arrays can be added and multipled using operator overloading instead of using "vector" in c++.
I defined a class named vector as follows,
class vector
{
private:
int len;
int *pvec;
}
public:
vector(int array[])
{
len = sizeof(array)/sizeof(*array);
cout<<len<<endl;
pvec = new int[len+1];
for(int i = 0;i<len;i++)
{
pvec[i] = *(array + i);
}
}
void display()
{
cout<<"[";
for(int i = 0;i<len;i++)
{
cout<<pvec[i];
if(i < len-1)
{
cout<<",";
}
}
cout<<endl;
}
};
and i declared an object of class vector as follows
int vec1[] = {1,2,3,4};
vector v(vec1);
when i try to display the elements in the vector using the member function as
v.display();
the output is as follows
2
[1,2]
but as you can see the length of the vector is 4, but in the output it is displayed as 2. If i try to display the length of the array in main as
cout<<sizeof(vec1)/sizeof(*vec1)<<endl;
the length is displayed as 4, but if i pass the same array to the object it is displayed as 2.
If any one could point out a mistake in this program, i would be grateful.
You cannot compute the size of an array once it is passed to a function as a pointer.
However, you can use couple of overloads of the constructor to help you with what you need.
In the first one, expect a pointer to an array and a size.
vector(int array[], int size) : len(size)
{
cout<<len<<endl;
pvec = new int[len+1];
for(int i = 0;i<len;i++)
{
pvec[i] = *(array + i);
}
}
In the second one, use a template with the size of the array as the
template parameter. Make it a delegating constructor that calls the first
one to do the work.
template <int N> vector(int (&array)[N]) : vector(array, N) {}
With this you can use:
// Use the first constructor
int* array1 = new int[20];
vector v1(array1, 20);
// Use the second constructor
int array2[10] = {0};
vector v2(array2);
See it working at http://ideone.com/RJN1gd.
There's no way, you should pass the length as an additional function's parameter.
Passing an array as a parameter is almost like passing a pointer to its first element, you loose every information about its size.

Choose at runtime array or vector in C++

I have a problem described as below ::
class datad {
private:
int *a;
int _size;
vector<int> v;
public:
datad(int arr[], int size) {
_size = size;
for (int i = 0; i < size; i++)
a[i] = arr[i];
}
datad(vector<int> ve)
{
v = ve;
_size = ve.size();
}
void printdata()
{
// print data which the object has been initialized with
// if object is initialized with vector then print vector
// array print array
}
};
int main()
{
// print only vector data
int a[] = { 9,4,8,3,1,6,5 };
datad d(v1);
d.printdata();
// print only array data
datad d1(a, 7);
d1.printdata();
}
I need to find the way the object is initialized and then based on the same should be able to printdata accrodingly.
Can someone help me understand if it is possible at all?
Add a bool usesVector to your class and set it to true or false in each constructor as appropriate. Then, in printdata, simply check the value of the boolean.
Or you can set size to -1 in the vector case (as it's otherwise unused) and just check for that.
By the way, your array implementation is broken, because you never allocate any memory for it. You'd be much better off using only the vector version. You can still initialise that vector from array data if you wish.
You can set a flag in respective constructor and check that flag during the printing method.
I hope this is for learning purposes, otherwise as noted you maybe better of using just the vector version. When using dynamic memory management in class you need to be aware of things like rule of three and I guess there is also rule of five.

C++: joining array together - is it possible with pointers WITHOUT copying?

as in the title is it possible to join a number of arrays together without copying and only using pointers? I'm spending a significant amount of computation time copying smaller arrays into larger ones.
note I can't used vectors since umfpack (some matrix solving library) does not allow me to or i don't know how.
As an example:
int n = 5;
// dynamically allocate array with use of pointer
int *a = new int[n];
// define array pointed by *a as [1 2 3 4 5]
for(int i=0;i<n;i++) {
a[i]=i+1;
}
// pointer to array of pointers ??? --> this does not work
int *large_a = new int[4];
for(int i=0;i<4;i++) {
large_a[i] = a;
}
Note: There is already a simple solution I know and that is just to iteratively copy them to a new large array, but would be nice to know if there is no need to copy repeated blocks that are stored throughout the duration of the program. I'm in a learning curve atm.
thanks for reading everyone
as in the title is it possible to join a number of arrays together without copying and only using pointers?
In short, no.
A pointer is simply an address into memory - like a street address. You can't move two houses next to each other, just by copying their addresses around. Nor can you move two houses together by changing their addresses. Changing the address doesn't move the house, it points to a new house.
note I can't used vectors since umfpack (some matrix solving library) does not allow me to or i don't know how.
In most cases, you can pass the address of the first element of a std::vector when an array is expected.
std::vector a = {0, 1, 2}; // C++0x initialization
void c_fn_call(int*);
c_fn_call(&a[0]);
This works because vector guarantees that the storage for its contents is always contiguous.
However, when you insert or erase an element from a vector, it invalidates pointers and iterators that came from it. Any pointers you might have gotten from taking an element's address no longer point to the vector, if the storage that it has allocated must change size.
No. The memory of two arrays are not necessarily contiguous so there is no way to join them without copying. And array elements must be in contiguous memory...or pointer access would not be possible.
I'd probably use memcpy/memmove, which is still going to be copying the memory around, but at least it's been optimized and tested by your compiler vendor.
Of course, the "real" C++ way of doing it would be to use standard containers and iterators. If you've got memory scattered all over the place like this, it sounds like a better idea to me to use a linked list, unless you are going to do a lot of random access operations.
Also, keep in mind that if you use pointers and dynamically allocated arrays instead of standard containers, it's a lot easier to cause memory leaks and other problems. I know sometimes you don't have a choice, but just saying.
If you want to join arrays without copying the elements and at the same time you want to access the elements using subscript operator i.e [], then that isn't possible without writing a class which encapsulates all such functionalities.
I wrote the following class with minimal consideration, but it demonstrates the basic idea, which you can further edit if you want it to have functionalities which it's not currently having. There should be few error also, which I didn't write, just to make it look shorter, but I believe you will understand the code, and handle error cases accordingly.
template<typename T>
class joinable_array
{
std::vector<T*> m_data;
std::vector<size_t> m_size;
size_t m_allsize;
public:
joinable_array() : m_allsize() { }
joinable_array(T *a, size_t len) : m_allsize() { join(a,len);}
void join(T *a, size_t len)
{
m_data.push_back(a);
m_size.push_back(len);
m_allsize += len;
}
T & operator[](size_t i)
{
index ix = get_index(i);
return m_data[ix.v][ix.i];
}
const T & operator[](size_t i) const
{
index ix = get_index(i);
return m_data[ix.v][ix.i];
}
size_t size() const { return m_allsize; }
private:
struct index
{
size_t v;
size_t i;
};
index get_index(size_t i) const
{
index ix = { 0, i};
for(auto it = m_size.begin(); it != m_size.end(); it++)
{
if ( ix.i >= *it ) { ix.i -= *it; ix.v++; }
else break;
}
return ix;
}
};
And here is one test code:
#define alen(a) sizeof(a)/sizeof(*a)
int main() {
int a[] = {1,2,3,4,5,6};
int b[] = {11,12,13,14,15,16,17,18};
joinable_array<int> arr(a,alen(a));
arr.join(b, alen(b));
arr.join(a, alen(a)); //join it again!
for(size_t i = 0 ; i < arr.size() ; i++ )
std::cout << arr[i] << " ";
}
Output:
1 2 3 4 5 6 11 12 13 14 15 16 17 18 1 2 3 4 5 6
Online demo : http://ideone.com/VRSJI
Here's how to do it properly:
template<class T, class K1, class K2>
class JoinArray {
JoinArray(K1 &k1, K2 &k2) : k1(k1), k2(k2) { }
T operator[](int i) const { int s = k1.size(); if (i < s) return k1.operator[](i); else return k2.operator[](i-s); }
int size() const { return k1.size() + k2.size(); }
private:
K1 &k1;
K2 &k2;
};
template<class T, class K1, class K2>
JoinArray<T,K1,K2> join(K1 &k1, K2 &k2) { return JoinArray<T,K1,K2>(k1,k2); }
template<class T>
class NativeArray
{
NativeArray(T *ptr, int size) : ptr(ptr), size(size) { }
T operator[](int i) const { return ptr[i]; }
int size() const { return size; }
private:
T *ptr;
int size;
};
int main() {
int array[2] = { 0,1 };
int array2[2] = { 2,3 };
NativeArray<int> na(array, 2);
NativeArray<int> na2(array2, 2);
auto joinarray = join(na,na2);
}
A variable that is a pointer to a pointer must be declared as such.
This is done by placing an additional asterik in front of its name.
Hence, int **large_a = new int*[4]; Your large_a goes and find a pointer, while you've defined it as a pointer to an int. It should be defined (declared) as a pointer to a pointer variable. Just as int **large_a; could be enough.

deleting an array that stores pointers to some objects

I am storing pointers to elements of a vec_A in an array A* a_ptrs[3] . Assume that vec_A will not be resized. So, a_ptrs[i] will point to the correct element.
My question is:
Suppose A* a_ptrs[3] is declared in a class B. Since it is not created using 'new' I am guessing I don't need to delete it in the destructor. Am I right??
class A {
public:
int getNumber();
A(int val);
~A(){};
private:
int num;
};
A::A(int val){
num = val;
};
int A::getNumber(){
return num;
};
int main(){
int i =0;
int num;
std::vector<A> vec_A;
for ( i = 0; i < 10; i++){
vec_A.push_back(A(i));
}
A* a_ptrs[3];
a_ptrs[0] = &vec_A[0];
a_ptrs[1] = &vec_A[3];
a_ptrs[2] = &vec_A[5];
for (i = 0; i<3; i++){
std::cout<<"\n: a_ptrs[i].getNumber() = "<<a_ptrs[i]->getNumber();
}
std::cout << "\nPress RETURN to continue...";
std::cin.get();
return 0;
}
Yep, thats correct. You don't need to use delete. The only issue is if the vector is resized e.g. by calling push_back etc - but you called that out in your post.
Yes, delete is used only for variables allocated with new.
Correct, since there is no dynamic memory allocation in the program.
My Suggestion is to use vector.reserve() function to reserve the size of the vector which will improve program performance.
Basically when you add an element to CArray(MFC) or std::vector it reallocates necessary memory and copies the elements so it will lead to memory fragmentation and will degrade program speed.