3

Ok i'm pretty new to c++ (I think what we are learning is somehow an hybrid of c and c++).
I've found alot of anwsers to my question, sadly all of them where in C using malloc.

struct A {
    int randomStuff = 0;    
};
struct B {
    int numOfA= 5;  // In reality this number is variable.
    A** arrayOfA;   
};

The struct are given to us. Now I need to allocate and fill this array with pointers to, I guess, A pointers. <- Correct me here if I'm wrong pointers are still quite complex for me.

A * a1 = new A;
A * a2 = new A;
B * b = new B;
// Allocate space for the array...
b->arrayOfA = new A*[numOfA];
// Next I want to initialize the pointers to NULL
for(int i; i < b->numOfA; i++){
    b->arrayOfA[i] = NULL;
}
// In another function I would the assign a value to it
b->arrayOfA[0] = a1;
b->arrayOfA[1] = a2;

The way I see it is that b->arrayOfA needs to point to an array of A struct...somehow like this

b->arrayOfA = new A*;
A * arr[numOfA];
b->arrayOfA = arr;

My brain is bleeding.
How do I correctly allocate it and assign existing values(A structs) to it?

*edit
It would appear that the code was working as intended and that my display was causing me issues. Basically, I needed an array "arrayOfA[]" in which I would put the pointers to an A struct. Effectively making the result of this:

cout << arrayOfA[0]->randomStuff // 0 would be displayed

To be 0.

5
  • 1
    main cannot return void. Are you trying to allocate a dynamic 2d array as an array of arrays? The C++ solution would be to use a vector of vectors. Commented Oct 22, 2014 at 22:15
  • Sorry about the main quite honnestly I don't know why I added it its quite irrelevant to the situation anyway. I'll remove it. While I've read about vectors and their wonders we are forced to use new and delete possibly to help us grow awareness of the memory. Commented Oct 22, 2014 at 23:25
  • The code before "The way I see it " is correct but then you go off on a crazy tangent. Stick with what you had! Commented Oct 22, 2014 at 23:38
  • Though C++ allows you to use malloc()/free(), you gain more benefit from the built-in memory management when you restrict yourself to new()/del(). You give one dimension of your array - do you intend for one-dimensional array, or two-dimensional array? Commented Oct 22, 2014 at 23:39
  • Yes it works now my displaying it was the issue :( do I need to close this post now that its fixed? If so how? Commented Oct 22, 2014 at 23:44

2 Answers 2

1

You could allocate an array of pointers and for each of them allocate an array of your objects

int x = 5, y = 6;
b->arrayOfA = new A*[x]; //array of pointers
for(int i=0;i<x;i++){
    b->arrayOfA[i] = new  A[y]; //matrix (array of arrays)
}

for(int i=0;i<x;i++){
    delete[] b->arrayOfA[i]; //don't forget to free memory
}
delete[] b->arrayOfA;
Sign up to request clarification or add additional context in comments.

2 Comments

It would appear that the code in the OP was working as intended and that my display was causing me issues. Basically, I needed an array arrayOfA[] in which I would put the pointer to an A struct. Effectively making the result of this: cout << arrayOfA[0]->randomStuff 0
@zoran404 when deleting a pointer allocated by new[], you use delete[] on that same pointer; you don't delete the individual array elements
0

You should be able to just use a vector:

#include <vector>

int main()
{
    vector<A> vector_of_a;
    vector_of_a.push_back(a1); //store a1 in the vector
    vector_of_a.push_back(a2); //store a2 in the vector
    //...
    std::cout << "Number of A's: " << vector_of_a.size() << std::endl;
    std::cout << vector_of_a[0].randomStuff << std::endl;  //prints 0 as specified but with '.' not '->'  Objects are still on the heap, and not the stack.
}

The A's in the vector are stored on the heap, but you don't need to manage the memory yourself (no need for malloc/free or new/delete. The A objects will be disposed of correctly when the vector goes out of scope.
You also get

You can push in pointers to objects too, but this reduces the usefulness of the vector as you then have to do your own memory management for the objects:

#include <vector>

int main()
{
    A* a1 = new A();
    A* a2 = new A();
    vector<A> vector_of_a;
    vector_of_a.push_back(a1); //store pointer to a1 in the vector
    vector_of_a.push_back(a2); //store pointer to a2 in the vector
    //...
    std::cout << "Number of A's: " << vector_of_a.size() << std::endl;
    std::cout << vector_of_a[0]->randomStuff << std::endl;  //prints 0 as specified
    //...
    for (auto i : vector_of_a)
    {
        delete (i);
    }
    vector_of_a.clear();
}

If you really don't want to use a vector, then I reccommend turning your struct B into a fully fledged class.
It gives you the benefit of encapsulation, functions to manage the data are stored within the class, and the class does the memory management and doesn't leave it to the user's code to manage and clear up behind it:

class B
{
public:
    array_of_A(unsigned int size);
    ~array_of_A();
    bool init_array();
    unsigned int get_size();
    A** get_array();
private:
    unsigned int num_of_A;
    A** array_of_A;
}

B::array_of_A(unsigned int size)
{
  num_of_a = size;
  array_of_A = new A*[size];          //create array
  memset (array_of_A, nullptr, size); //initialise contents to nullptr
}

B::~B()
{
    for(unsigned int i = 0; i < num_of_a; i++)
    {
        delete array_of_a[i]; //delete each A
    }
    delete[](array_of_a);     //delete the array of pointers.
}

unsigned int B::get_size()
{    return num_of_A;    }

A** B::get_array()
{    return array_of_A;    }

int main()
{
    B b((5));     //most vexing parse...

    b.get_array()[0] = new A();
    b.get_array()[1] = new A();
    b.get_array()[2] = new A();

    std::cout << b.get_array()[0]->randomStuff << std::endl //prints 0 as requested

}   //b goes out of scope, destructor called, all memory cleaned up

aaaand by internalising the memory management and supporting arbitarilly long arrays, we've just started implementing a (much) simpler version of vector. But good for practice/learning.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.