How to add data to an array of pointers? - c++

I created an array of pointers.
I want to know how to prp=operly add data to my array of pointers.
I have attempted the code below, unfortunately it is giving me a memory error and I do not know why.
class dataClass {
int data;
public:
void setdata(int d) {data = d;}
int getdata() const {return data;}
};
int main() {
dataClass** ptr = new dataClass*s[5];
int num = 9;
ptr[0] -> setdata(num);
return 0;
}

You just allocate the memory for the pointers (not for the objects), so ptr[0] points to an unspecified address and you get a segfault.
You need to add something like this:
for(int i = 0; i < 5; i++) {
ptr[i] = new dataClass;
}

When using a pointer-to-pointer-to-type, you must allocate storage for the required number of pointers and then allocate storage for each class which you then assign to each pointer.
For example, using 5 pointers as you attempt in your questions, you would first need to allocate for the pointers, e.g.
#define NPTRS 5
...
dataClass** ptrs = new dataClass *[NPTRS];
Now you have storage allocated for 5 pointers to type dataClass with the address for the initial pointer assigned to ptrs (I added the plural form for clarity)
The storage for the pointers is now allocated, but each of the allocated pointers does not yet point to valid storage for dataClass, they are just pointers. Before you can use the pointers to reference an instance of the class, you must allocate storage for each each class instance and then assign the address of the new block of memory to each of your pointers, e.g.
for (int i = 0; i < NPTRS; i++) {
ptrs[i] = new dataClass;
ptrs[i]->setdata (i+1);
}
(above you allocate storage for each class instance assigning the result to ptrs[i] and then set the data value to i+1)
Putting it altogether, you could do something similar to:
#include <iostream>
#include <cstdlib>
#define NPTRS 5
class dataClass {
int data;
public:
void setdata(int d) {data = d;}
int getdata() const {return data;}
};
int main() {
dataClass** ptrs = new dataClass *[NPTRS];
for (int i = 0; i < NPTRS; i++) {
ptrs[i] = new dataClass;
ptrs[i]->setdata (i+1);
}
for (int i = 0; i < NPTRS; i++)
std::cout << "ptrs[" << i <<"]->getdata() : "
<< ptrs[i]->getdata() << '\n';
return 0;
}
(note: don't forget you are responsible for keeping track of what you allocated and calling delete to free each allocation when it is not longer needed)
Example Use/Output
$ ./bin/dblptr2class
ptrs[0]->getdata() : 1
ptrs[1]->getdata() : 2
ptrs[2]->getdata() : 3
ptrs[3]->getdata() : 4
ptrs[4]->getdata() : 5
As others have mentioned, the C++ containers like vector are for less error prone and make your job a lot easier. Still, you should know how to handle both new/delete as well as the use of the containers.
Look things over and let me know if you have further questions.

You could first create an array of objects
(constructors will be called automatically).
After that create a pointer to your pointer:
#include <stdio.h>
class dataClass {
int data;
public:
dataClass(){
printf(" new instance \n");
}
void setdata(int d) {
data = d;
printf(" setdata \n");
}
int getdata() const {return data;}
};
int main() {
dataClass* ptr = new dataClass[5];
dataClass** pptr = &ptr;
int num = 9;
pptr[0]->setdata(num);
return 0;
}
result:
new instance
new instance
new instance
new instance
new instance
setdata

Related

freeing the same memory with distructors

I try to free the memory correctly after the program ends, but I always encounter a problem.
In my code I want to have an array of all the numbers that I allow in my program, and have objects A and B (or more) that each one have some of the numbers that I allowed.
In the end I want to delete 'a' and 'b' only after "ints" getting out of the scope. But A and B calls their distructors to delete some of ints variables.
#define MAX_LEN 255
class IntArray
{
public:
int len;
void add(int* n) {
arr[len] = n; len++;
}
IntArray() : arr(new int* [MAX_LEN]), len(0) {}
~IntArray() {
for (int i = 0; i < len; i++)
delete arr[i];
delete[] arr;
}
private:
int** arr;
};
class Object
{
public:
void add(int* n) {
myIntArr.add(n);
}
private:
IntArray myIntArr;
};
int main(void)
{
int* a = new int(5);
int* b = new int(6);
IntArray ints;
ints.add(a);
ints.add(b);
Object A;
A.add(a);
Object B;
B.add(b);
return 0;
}
If you want to share dynamically allocated ints between multiple objects, use std::shared_ptr<int>.
Also, rather than writing a dynamic array type yourself, use std::vector to do it (correctly) for you.
using int_ptr = std::shared_ptr<int>;
class IntArray
{
public:
void add(int_ptr n) {
arr.push_back(n);
}
private:
std::vector<int_ptr> arr
};
class Object
{
public:
void add(int_ptr n) {
myIntArr.add(n);
}
private:
IntArray myIntArr;
};
int main(void)
{
int_ptr a = std::make_shared<int>(5);
int_ptr b = std::make_shared<int>(6);
IntArray ints;
ints.add(a);
ints.add(b);
Object A;
A.add(a);
Object B;
B.add(b);
return 0;
}
If you just want to have a copyable array of int, use std::vector<int>.
You're deleting a and b twice.
You should only delete something returned by new and exactly once.
But you add them both to IntArray ints; and then one each to Objects A and B and their destructors delete them also. Destructors are called in reverse order to it's when ints is destructed you'll be deleting them again - that's "Undefined Behaviour" but normally a catastrophic failure (crash) either immediately or later during executon.
The shortest fix is:
int* a = new int(5);
int* b = new int(6);
int *ac = new int(*a);//copy of *a
int *ab = new int(*b);//copy of *b
IntArray ints;
ints.add(a);
ints.add(b);
Object A;
A.add(ac);
Object B;
B.add(bc);
But it's not clear what our intention is. IntArray isn't an array of int as it stands, it's an array of pointers to int (which have been allocated by new).
My 'fix' will mean if you modify a (e.g. *a=20) you won't modify the copy (ac) added to the Object A.

Destructor call in a class constructor with a vector

I have the following class which simply wraps an array and adds with the constructor some elements to it:
class myArray {
public:
myArray();
myArray(int a, int b);
myArray(int a, int b, int c);
myArray(myArray&& emplace);
~myArray();
int& operator [](int id);
private:
int *data;
};
myArray::myArray() {
data = new int[1];
data[0] = 0;
}
myArray::myArray(int a, int b) {
data = new int[3];
data[0] = 0;
data[1] = a;
data[2] = b;
}
myArray::myArray(int a, int b, int c) {
data = new int[4];
data[0] = 0;
data[1] = a;
data[2] = b;
data[3] = c;
}
myArray::~myArray() {
std::cout << "Destructor"<<std::endl;
delete[] data;
}
int& myArray::operator [](int id) {
return data[id];
}
myArray::myArray(myArray&& emplace) : data(std::move(emplace.data)) {}
Furthermore I have a second class which contains a vector of elements of the first class (myArray).
class Queue {
public:
Queue();
private:
std::vector<myArray> _queue;
};
Queue::Queue {
_queue.reserve(1000);
for(int a = 0; a < 10; a++)
for(int b = 0; b < 10; b++)
for(int c = 0; c < 10; c++)
_queue.emplace_back(a,b,c);
}
My question here is: Why is the destructor called for the myArray elements at the end of the Queue constructor? The Queue object is still alive in my main program but the destructor of myArray frees the allocated memory and I consequently get a segmentation fault.
Is there a way to avoid the call of the destructor or rather call it not until at the end of the Queue objects lifetime?
Your move constructor doesn't set data to null on the moved from object so when the moved from object is destructed it will try to free data.
If you have c++14 you can use std::exchange to implement this:
myArray::myArray(myArray&& emplace)
: data{std::exchange(emplace.data, nullptr)})
{}
Otherwise you need to do:
myArray::myArray(myArray&& emplace)
: data{emplace.data)
{
emplace.data = nullptr;
}
The move constructor will be invoked by std::vector as it reallocates to increase its capacity when you call emplace_back. Something like the following steps are performed:
Allocate new memory to hold the elements
Move construct using placement new elements in the new memory from the elements in the previous memory
Destruct the elements in the previous memory
Deallocate the previous memory

Problem using malloc() for C++ string object in VC++, but no problem with new

Here is a simple code:
#include <iostream>
#include <string>
typedef struct Car{
std::string model;
} Car;
std::string get_model() {
std::string str = "Maserati";
return str;
}
int main() {
const int nCars = 2;
//Car *list = new Car[nCars]; // works everywhere g++/VC++
Car *list = (Car *)malloc(nCars * sizeof(Car)); // works in g++, not VC++
list[0].model = get_model();
std::cout << "model=" << list[0].model << std::endl;
// delete[] list;
free(list);
return 0;
}
There is no problem when I used malloc() or new in g++. However, malloc() does not work in Visual C++. Should I use new always when I allocate the C++ class object?
(a debtor)<><
You are allocating memory without calling a constructor or calling the destructor when the object is about to be removed. This is what new[] and delete[] does for you, so use them - or better yet, use smart pointers - or even better, a standard container, like std::vector to keep the objects for you.
Your code with the missing parts added:
#include <iostream>
#include <string>
struct Car {
std::string model;
Car() { std::cout << "ctor\n"; }
~Car() { std::cout << "dtor\n"; }
};
int main() {
const int nCars = 2;
// allocate memory
Car *list = (Car *)malloc(nCars * sizeof(Car));
// manually calling constructors
for(int i=0; i<nCars; ++i) {
new(&list[i]) Car();
}
// use objects here
// manually calling destructors
for(int i=0; i<nCars; ++i) {
list[i].~Car();
}
// freeing memory
free(list);
}
Compare with using new[] and delete[]:
int main() {
const int nCars = 2;
// create cars
Car* list = new Car[nCars];
// use objects here
// delete cars
delete[] list;
}
Compare with using a container:
int main() {
const int nCars = 2;
// create cars
std::vector<Car> list(nCars);
// use objects here
}
Yes.
While it is wrong to say, "Never use malloc() in C++," it is definitely true that you should never use malloc() to instantiate a class.
Keep in mind that C++ is, in a sense, a hybrid language in that it effectively supports an almost complete subset of C and adds the superset of C++ functionality. malloc() has a role to play when using built-in types like int, char, float, etc.
For objects, however, new must be used. It might be true that you have found that malloc() works in many cases, but new and delete will cause constructors and destructors to be called, which will never happen with malloc() and free().
The problem here is because you're allocating a memory for the std::string of your Car struct but do not call the std::string constructor.
You should call a placement new for each item in the array to call the constructor and initialize the std::string field in the Car struct:
int main() {
const int nCars = 2;
Car* list = (Car *)malloc(nCars * sizeof(Car));
for (int i = 0; i < nCars; ++i)
new(&list[i])Car();
list[0].model = get_model();
std::cout << "model=" << list[0].model << std::endl;
}
-- ORIGINAL ANSWER --
Here's my original answer (which is inorrect due to an extra overhead that may be required for arrays: https://en.cppreference.com/w/cpp/language/new#Allocation)
If you have to use malloc then I suggest you use a in-place constructor with the returned memory block:
int main() {
const int nCars = 2;
Car *list = new (malloc(nCars * sizeof(Car)))Car[nCars];
list[0].model = get_model();
std::cout << "model=" << list[0].model << std::endl;
return 0;
}

Create Array Using Pointers

i'm working on a array header from base definition of an array to create an array of any type with this header,so i created a array class with functions and constructors.
this is my code so far:
#include <iostream>
#define newline "\n"
class Arr
{
public:
typedef float T;
public:
Arr(int size);
Arr(int size, T fill);
T get(unsigned index) const;
void set(unsigned index, T newvalue);
unsigned Size() const;
unsigned SIZE;
void Print();
private:
};
Arr::Arr(int size,T fill)
{
SIZE = size;
T *pointer;
for (int i = 0; i < size; i++)
{
*pointer = fill;
pointer++;
}
}
void Arr::set(unsigned index, T newvalue)
{
T *pointer;
pointer = 0;
for (unsigned i = 0; i < index; i++)
{
pointer++;
}
*pointer = newvalue;
}
void Arr::Print()
{
T *pointer;
pointer = 0;
for (unsigned i = 0; i < SIZE; i++)
{
std::cout << *pointer << newline;
pointer++;
}
}
i know that my pointer point to nothing,as my question is my pointer should point to what to make this code work correctly?!
any time i point it to 0 after debug it crashes!
thanks...!
Pointers are tricky part of c++.
Here is a good link to get you started
http://www.codeproject.com/Articles/7042/How-to-interpret-complex-C-C-declarations
The reason your code doesn't work is a memory block for the array pointed to by the pointer is not allocated. You have to use the predecessor new in-order to achieve that.
Here an example
int size;
T arr;
T* ptr_2_arr;
ptr_2_arr = new T[size];
To retrieve elements of the array you can loop the array using a for loop
*ptr_2_arr[i];
hope this helps.
Post the problem statement if you need more detail
You must make a data member of the class that will point to the allocated memory for the array. Also you need to define a copy constructor, the copy assignment operator and the destructor.
Also it would be better that type of parameter size of constructors coinsides with the type of data member SIZE, I do not understand why this variable is written in capital letters.
ALso there is no any sense to make the data member SIZE and the function Size() public. if SIZE is public it can be changed by the user at any moment.
Make sure you specify the size of the array in your constructor.
SIZE = size;
pointer = new T[size]; //this is where I see an issue. Specify the size of your array.
for (int i = 0; i < size; i++)
{
*(pointer + i) = fill; //This is fine but you are filling up the array with only one number, fill. Nothing wrong with that if that is you intention. Try (*(pointer + i) = i; for i though size elements.
}

Dynamic memory in a class (Allocating memory and accessing to the elements)

I have a simple class aClass:
class aClass
{
public:
aClass(int size)
{
condition = new bool[size];
}
~aClass()
{
delete condition;
}
bool getCondition(int i) const
{
return condition[i];
}
void setCondition(bool* condition, int i)
{
*(this->condition + i) = *condition;
}
private:
bool* condition;
};
In fact I defined a bool pointer and using constructor to allocate memory.
#include <iostream>
#include "aClass.h"
using namespace std;
int main()
{
aClass tempVar(10);
bool *pC;
for (int i = 0; i < 10; i++)
{
*pC = 0;
tempVar.setCondition(pC, i);
}
for (int i = 0; i < 10; i++)
{
cout << tempVar.getCondition(i);
}
return 0;
}
I do not know what is the problem in this code.
I used gcc version 4.6.3 to compile the code.
You are trying to dereference pC although you never initialized the pointer. Probably pC should have type bool, not bool*, at the same time *pC = 0 should likely be pC = 0 and setCondition should likely take bool not bool*.
You delete although it should be delete[], see here why: delete vs delete[]
Your code will try to delete allocated memory twice if an instance of aClass is copied somewhere. See Rule of three.
You should use std::vector instead of the manually allocated array.
There are two mutually exclusive problems here:
You haven't initialized pC. Do this:
int main() {
⋮
bool * pC = new bool;
⋮
delete pC;
}
Actually, raw pointers aren't such a good idea, so this is better:
std::unique_ptr<bool> pC(new bool);
// No delete required.
setCondition() doesn't need a pointer parameter at all:
class aClass {
⋮
void setCondition(bool cond, int i) {
condition[i] = cond;
}
⋮
};
int main() {
⋮
for (int i = 0; i < 10; ++i) {
tempVar.setCondition(false, i);
}
⋮
}