Delete a pointer with a pointer to that pointer - c++

Well consider this:
int * hello = new int[10];
for (register int i = 0; i < 10; i++)
*(hello + i) = i;
int * & hello_ref = hello;
delete[] hello_ref ;
for (register int i = 0; i < 10; i++)
cout << *(hello + i) << std::endl;
Nowhello_ref can succesfully delete the memory which is allocated by new ... From a fact that the reference and pointer are very close how we do the same thing with pointer to pointer to new memory allocated
now consider this
int i = 0;
unsigned int * hello = new unsigned int[6];
for (register int i = 0; i < 6; i++)
*(hello + i) = i;
unsigned int * bye = new unsigned int[4];
for (register int i = 0; i < 4; i++)
*(bye + i) = i;
unsigned int ** del = new unsigned int *[2];
*del = bye;
*(del + 1) = hello;
delete[] * del;
delete[] * (del + 1);
Is there any way that we could delete the new allocated memory for hello and bye with the del pointer to pointer ... these could just clear the data which hello and bye pointed to ....

You just need to delete the array referenced by del:
delete[] del;
You are already deleting the arrays referenced by hello and bye:
delete[] * del;
delete[] * (del + 1);
Though this would be more idiomatic:
delete[] del[0];
delete[] del[1];
Or even better, avoid using new and delete altogether, taking advantage of modern C++ features. What you are writing looks more like C.
#include <array>
#include <numeric>
#include <tuple>
template<typename T, std::size_t N>
std::array<T, N> make_increasing_array(T initial = T())
{
std::array<T, N> array;
std::iota(array.begin(), array.end(), initial);
return array;
}
int main()
{
auto del = std::make_tuple(
make_increasing_array<unsigned int, 6>(),
make_increasing_array<unsigned int, 4>());
auto& hello = std::get<0>(del);
auto& bye = std::get<1>(del);
}

If I understand your question correctly then the answer on the 1st part of your question will be something like this:
...
int * * hello_ref = &hello;
delete[] *hello_ref;
...
About second part, you did exactly what you asked. Those 2 delete do the job. Just add delete[] del; as a final touch.

Related

Valgrind errors from dynamically allocated arrays in C++

The program is aimed to take a dynamically allocated array and return a new dynamically allocated array with double the size that copies the values in the first one and leaves the rest uninitialized. However, it's getting valgrind errors in main(). Any suggestions on how to fix the memory issues?
#include <iostream>
using std::cout;
using std::endl;
int * doubleSize(int * p, int & cap) {
//create dynamically allocated double size array
int *doubleSize = new int(cap * 2);
//store old array values into new array
for (int i = 0; i < cap; i++) {
doubleSize[i] = p[i];
}
cap = cap * 2;
delete[] p; //deallocate old memory
return doubleSize;
}
int main() {
int cap = 3;
int *p = new int(cap);
//initialize an array
for (int i = 0; i < cap; i++) {
p[i] = i;
}
int *s = doubleSize(p, cap);
for (int i = 0; i < 6; i++) {
cout << s[i] << endl;
}
//deallocate memory
delete p;
delete s;
}
Several problems in the code:
int *p = new int(cap);
and
int *doubleSize = new int(cap * 2);
both allocate a single int with the value cap or cap * 2
Since arrays of int are expected by the rest of the code, these need to be corrected to
int *p = new int[cap];
and
int *doubleSize = new int[cap * 2];
Then
delete p;
delete s;
must be changed to
delete[] p;
delete[] s;
in order to correctly delete arrays.
But!
delete[] p;
already happened back in doubleSize when the array was replaced. It could be removed, but the code would be cleaner with
p = doubleSize(p, cap);
and the variable s being removed instead.

how to have a copy constructor for vector?

I simulated a vector but the constructor doesn't work; when I call pop() function it assigns garbage value to my old object in vector class.
vector(vector &v) {
vec = new T[v.size()];
memcpy(vec, v,v.size());
size_arr = v.size();
}
here's entire code:
#include <iostream>
using namespace std;
template <typename T>
class vector {
int size_arr;
T * vec = new T;
public:
vector(/*int _size*/) {
vec = new T[0];
size_arr = 0;
};
~vector() {
size_arr = 0;
delete[] vec;
};
vector(vector &v) {
vec = new T[v.size()];
memcpy(vec, v,v.size());
size_arr = v.size();
}
void push_back(T data) {
T *temp = new T[size_arr + 1];
for (int i = 0; i < size_arr; i++)
temp[i] = vec[i];
temp[size_arr] = data;
size_arr++;
delete[] vec;
vec = temp;
};
void push_front(T data){
int j;
T *temp = new T[size_arr + 1];
for ( j = size_arr; j >= 0;j--) {
temp[j + 1] = vec[j];
}
temp[0] = data;
delete[] vec;
vec = temp;
size_arr++;
};
void insert(int index, T data) {
int j;
T *temp = new T[size_arr + 1];
for (int i = 0; i < size_arr ;i++)
temp[i] = vec[i];
for (int i = 0; i < size_arr;i++) {
if (i == index) {
for ( j = size_arr; j >=i;j--) {
temp[j+1] = vec[j];
}
temp[j + 1] = data;
delete[] vec;
vec = temp;
size_arr++;
}
}
};
void pop() {
T *temp = new T[size_arr - 1];
for (int i = 0; i < size_arr-1;i++)
temp[i] = vec[i];
size_arr--;
delete[] vec;
vec = temp;
};
void Delete(int index)
{
T *temp = new T[size_arr - 1];
for (int i = 0; i < index;i++)
temp[i] = vec[i];
for (int i = 0; i < size_arr;i++) {
if (i == index) {
for (int j = i; j < size_arr-1;j++) {
temp[j] = vec[j + 1];
}
size_arr--;
delete[] vec;
vec = temp;
}
}
};
int search(T data) {
for (int i = 0; i < size_arr;i++) {
if (vec[i] == data) {
return i;
}
}
return -1;
};
int size() { return size_arr; };
};
int main() {
vector <int>test;
test.push_front(2);
test.push_front(3);
test.push_back(0);
test.push_back(-1);
test.insert(2, 2);
test.pop();
vector <int > test1;
test1 = test;// problem
test1.pop();
}
The problem is the line test1 = test;// problem, which does not call the copy constructor, but the assignment operator. You did not declare this operator, so the compiler will use the default implementation, which simply copies all member. So, after the assignment test1.vec and test.vec point to the same memory location.
When you change the line (and the one above it) to vector <int > test1{test};, it will call your copy constructor.
You also forgot to #include <cstring> for memcpy, which you should not use for non-POD types.
You have to multiply the size in memcpy with sizeof(T), because memcpy works on bytes, not on types. You also have to use v.vec instead of v.
Here is the fixed version: https://ideone.com/JMn7ww
I think the problem is in your copy operator. You use memcpy() which is a c function. Which should in itself not be a problem (apart from it being not so nice in many opinions). But since memcpy() is a c function, it doesn't know about types, and it takes its size arguments as a count of bytes.
the element you put in is int which is probably 4 bytes. So when your copy contstructor gets called, and the original has 3 elements, there will be 12 bytes in your array, but malloc will only copy 3 of them.
The comments of other people about not properly copying template types are right, so if you make a vector of strings, you cannot just memcpy them, and assume the result will be new strings. For this answer i was assuming you using only basic types as your template arguments like int, or double.

Assigning memory

I'm trying to assign memory por double *r[3]
Whenever I try this way it keep failing:
#include <cstdio>
int main(){
int N = 10;
double *r[3] = new double[N][3];
delete r;
return 0;
}
How is the correct way?
You need to assign blocks of memory to each cell your pointer points to.
double **r = new double* [N];
for(int i = 0; i < N; i++)
{
*(r + i) = new double[3];
delete [] *(r + i);
}
delete [] r;
Better is to use std::vector:
std::vector<std::vector<double>> r;
Use
double (*r)[3] = new double[N][3];
and
delete [] r;
Just use std::array
#include <array>
int main()
{
int N = 10;
typedef std::array<double,3> darray;
darray *r = new darray[N];
delete []r;
return 0;
}

C++ error reading character of string

I am trying to add an array to my Object which contains dynamic array
MyCollection.h
template <typename T>
MyCollection<T>::MyCollection(int size)
{
arraySize = size;
anArray = new T[size];
}
template <typename T>
MyCollection<T>::MyCollection(MyCollection<T>& coll)
{
arraySize = coll.arraySize;
anArray = new T[arraySize];
for (int i = 0; i < arraySize; i++)
{
SetValue(coll.GetValue(i), i);
}
}
template <typename T>
MyCollection<T>::MyCollection(T* myArray, int size)
{
anArray = myArray;
arraySize = size;
}
template<typename T>
void MyCollection<T>::AddAll(T pArray[], int size)
{
int plusSize = size - 1;
int arrayIterator = 0;
arraySize += size;
for (int i = size; i < arraySize - plusSize; i++)
{
anArray[i] = pArray[arrayIterator];
arrayIterator++;
}
}
Main
MyCollection<string> B = MyCollection<string>(new string[3], 3);
B.SetValue("C", 0);
B.SetValue("D", 1);
B.SetValue("E", 2);
string C[3];
C[0] = "X";
C[1] = "Y";
C[2] = "Z";
B.AddAll(C, 3);
B.Display();
In the AddAll method I have error with acces violation. When I add watch anArray[i] = . Is there any idea why that happens? Is it problem with copy construcotr or so ?
In AddAll(), you need to resize the raw array anArray, there is no resizing going on (you just change the numeric value of arraySize, but do not allocate more memory). So you need something like
delete[] anArray;
// ...
anArray = new T[arraySize];
You may also think whether you want to copy the old elements into the newly allocated array, in which case you first have to reallocate with a temporary pointer, then copy into it, then delete the original anArray, and finally assign the temporary pointer to the original anArray, something like:
// save the old size
int oldSize = arraySize;
arraySize += size;
T* tmp = new T[arraySize];
// copy from anArray into tmp, use oldSize
// for(...){...}
delete[] anArray;
anArray = tmp;

Allocate and initialize pointer in local function

I want to allocate memory and fill it to the pointer, that are one of the function parameter, but I think that I don't get some important thing, help me please.
So, If I do that everything works fine:
void alloc(char **p, int n)
{
*p = new char[n];
}
int main() {
char * ptr = NULL;
int n = 10;
alloc(&ptr, n);
for(int i = 0; i<(n - 1); i++)
ptr[i] = '1';
ptr[n - 1] = '\0';
printf("%s", ptr);
return 0;
}
Now I want to initialize the allocated memory also into the function
void alloc(char **p, int n)
{
*p = new char[n];
for(int i = 0; i<(n - 1); i++)
*p[i] = '1';
*p[n - 1] = '\0';
}
int main() {
char * ptr = NULL;
int n = 10;
alloc(&ptr, n);
printf("%s", ptr);
return 0;
}
Program crashes. I don't get why. Please, can someone explain?
Try (*p)[i] and (*p)[n - 1] instead. The precedence rules cause *p[i] to be evaluated as *(p[i]).
Try this:
((*p)[i]) = '1';
you have a problem with operator's evaluation order.
Probably because this:
*p[i]
is interpreted as if you had written this:
*(p[i])
not as if you had written this, which is what you probably meant:
(*p)[i]
This should do the trick,
void
alloc( char*& p, int n )
{
p = new char[n];
std::fill_n( p, n - 1, '1' );
p[n - 1] = '\0';
}
If you insist on using a pointer as argument, change all of the p
in the function to (*p) (and don't forget to check for a null pointer
and do something reasonable if you're passed one.
All things considered, however, you'd be better off using
std::string—this function wouldn't even be necessary, as you
could write std::string( n, '1' ).
Try this
#include <stdio.h> // for NULL
void alloc(char **p, int n)
{
*p = new char[n];
for(int i = 0; i<(n - 1); i++)
*((*p) + i) = '1';
*((*p) + n - 1) = '\0';
}
int main() {
char * ptr = NULL;
int n = 10;
alloc(&ptr, n);
printf("%s", ptr);
// never forget delete pointers
delete [] ptr;
return 0;
}
Its a precedence of operators issue. Try this in your alloc function:
for(int i = 0; i<(n - 1); i++)
(*p)[i] = '1';
(*p)[n - 1] = '\0';