Pointer to an array of pointers

A

Andy Gibbs

Hello!

Please could someone help me with what is probably a trivial problem, but is
definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.

I believe I am also correct with my accessor function:

MyObject& item(int index) {
return *((*pointer)[index]);
}

However, I am having real difficulty working out how to use new and delete
with my pointer. So the following doesn't work:

pointer = new MyObject*[size];
for (int i = size; i-->0;)
(*pointer) = new MyObject(...);

Because the first line fails compile with "cannot convert DbString** to
DbString*(*)[] in assignment". (I am using GCC 4.1.2.)

The following use of delete compiles, but I am not sure it does what I think
(hope?) it does!

for (int i = size; i-->0;)
delete (*pointer);
delete[] pointer; // should this be delete[] *pointer ?


Please, any help will be very gratefully appreciated!

Andy.
 
A

Alf P. Steinbach

* Andy Gibbs:
Please could someone help me with what is probably a trivial problem, but is
definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.

Use a std::vector.

I believe I am also correct with my accessor function:

MyObject& item(int index) {
return *((*pointer)[index]);
}

However, I am having real difficulty working out how to use new and delete
with my pointer. So the following doesn't work:

pointer = new MyObject*[size];
for (int i = size; i-->0;)
(*pointer) = new MyObject(...);


Use a std::vector instead.

Because the first line fails compile with "cannot convert DbString** to
DbString*(*)[] in assignment". (I am using GCC 4.1.2.)
Good.


The following use of delete compiles, but I am not sure it does what I think
(hope?) it does!

for (int i = size; i-->0;)
delete (*pointer);
delete[] pointer; // should this be delete[] *pointer ?


Please, any help will be very gratefully appreciated!


Use a std::vector instead.


Cheers & hth.,

- Alf
 
A

Andy Gibbs

Alf said:
* Andy Gibbs:
Please could someone help me with what is probably a trivial problem, but
is definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.

Use a std::vector.

...


Alf, thanks for your reply. I have considered the use of a number of
dynamic array implementations, but unfortunately they really aren't
suitable in my application.

I can understand that the way the question is posed leads to such an answer,
because I simplified it to make it understandable, but using std::vector
won't work in this case -- sorry, I should have said so in the
question! ;o)

Thanks
Andy
 
P

Pascal J. Bourguignon

Andy Gibbs said:
Hello!

Please could someone help me with what is probably a trivial problem, but is
definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.

You can skip the array. A pointer is automatically a pointer to an array.

class MyObject {
public:
MyObject(){};
};

int main(){
MyObject** pointer;

pointer=new MyObject* [4];

pointer[0]=new MyObject();
pointer[1]=new MyObject();
pointer[2]=new MyObject();
pointer[3]=new MyObject();

delete pointer[0];
delete pointer[1];
delete pointer[2];
delete pointer[3];

delete [] pointer;

return(0);
}

/*
-*- mode: compilation; default-directory: "/tmp/" -*-
Compilation started at Fri Feb 13 13:33:25

SRC="/tmp/a.c++" ; EXE="a" ; g++ -g3 -ggdb3 -o ${EXE} ${SRC} && ./${EXE} && echo status = $?
status = 0

Compilation finished at Fri Feb 13 13:33:25

*/

I believe I am also correct with my accessor function:

MyObject& item(int index) {
return *((*pointer)[index]);
}

Since you have an array of pointers, why do you want to return a reference?

However, I am having real difficulty working out how to use new and delete
with my pointer. So the following doesn't work:

pointer = new MyObject*[size];
for (int i = size; i-->0;)
(*pointer) = new MyObject(...);

Because the first line fails compile with "cannot convert DbString** to
DbString*(*)[] in assignment". (I am using GCC 4.1.2.)


See the difference between your post and my answer. Your post doesn't
contain full source code, compilable. Mine does. If it had an error,
you could debug it.

The following use of delete compiles, but I am not sure it does what I think
(hope?) it does!

for (int i = size; i-->0;)
delete (*pointer);
delete[] pointer; // should this be delete[] *pointer ?


No. You want to delete the memory pointed to by pointer, not by
*pointer (which is pointer[0]). See my code.
 
A

Alf P. Steinbach

* Andy Gibbs:
Alf said:
* Andy Gibbs:
Please could someone help me with what is probably a trivial problem, but
is definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.
Use a std::vector.

...


Alf, thanks for your reply. I have considered the use of a number of
dynamic array implementations, but unfortunately they really aren't
suitable in my application.

I can understand that the way the question is posed leads to such an answer,
because I simplified it to make it understandable, but using std::vector
won't work in this case

Why?

- Alf
 
F

Fraser Ross

However, I am having real difficulty working out how to use new and
delete
with my pointer. So the following doesn't work:

pointer = new MyObject*[size];
for (int i = size; i-->0;)
(*pointer) = new MyObject(...);


The return type of operator new here must be MyObject*.

Fraser.
 
V

Vidar Hasfjord

Hello!

Please could someone help me with what is probably a trivial problem, but is
definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.

I assume you take that to mean a "dynamic array" of any size, but
there is no such built-in type in C++. Actually, using empty square
brackets in a type expression means that the type is incomplete (i.e.
not fully specified).

There is severe restrictions on how you can use incomplete types. In
particular there is no implicit conversion from a pointer to a
complete type to a pointer to an incomplete type, e.g.

int (*a) [2];
int (*p) [] = a; // error: cannot convert from 'int (*)[2]' to 'int
(*)[]'
...
However, I am having real difficulty working out how to use new and delete
with my pointer. So the following doesn't work:

pointer = new MyObject*[size];

The type of the right hand side is not what you seem to expect; new
does not return a pointer to an array (MyObject* (*) [size]). Even if
it did, you could not assign that pointer to your pointer, because the
latter points to an incomplete type as I explained above.

Actually, the new operator has very irregular behaviour for array
types:

typedef struct Scalar {int i;};
Scalar* s = new Scalar; // works; returns Scalar*

typedef int Array [1];
Array* a = new Array; // fails; returns int**

The new operator will never allocate an array and return a pointer to
it. For arrays it will instead allocate a number of contiguous
elements and return a pointer to the first element. This is an
irregular feature stemming from the unfortunate reuse of the square
brackets to pass an argument to new at run-time.

If the size of your array (and hence its type) is known at compile-
time, then you can circumvent these irregularities by using an array
wrapper such as tr1::array:

typedef std::tr1::array <MyObject*, size> A;
A* pointer = new A; // works; returns A*

If the size is not known until run-time you will have to scrap arrays
and use pointers, or preferably a container type such as std::vector,
instead.

General tip: Use typedef to simplify type expressions.

Regards,
Vidar Hasfjord
 
C

Chris Gordon-Smith

Andy Gibbs said:
Alf said:
* Andy Gibbs:
Please could someone help me with what is probably a trivial problem, but
is definitely tying me in knots!

I have a class MyObject, and I need to create a pointer to an array of
pointers to this class. I think I am correct with the definition of...

MyObject* (*pointer)[];

which I take to mean a pointer to an array of MyObject pointers.

Use a std::vector.

...


Alf, thanks for your reply. I have considered the use of a number of
dynamic array implementations, but unfortunately they really aren't
suitable in my application.

I can understand that the way the question is posed leads to such an answer,
because I simplified it to make it understandable, but using std::vector
won't work in this case -- sorry, I should have said so in the
question! ;o)

Thanks
Andy

It seems to me that the STL was designed to do exactly the kind of thing
you are trying to do. Please post more details. If it really is the case
that the particular kind of array of pointers (or pointer to it) that you
need cannot be handled with std:vector, then it will be of interest (to me
at least).
 
J

James Kanze

Please could someone help me with what is probably a trivial
problem, but is definitely tying me in knots!
I have a class MyObject, and I need to create a pointer to
an array of pointers to this class. I think I am correct
with the definition of...
MyObject* (*pointer)[];
which I take to mean a pointer to an array of MyObject pointers.
You can skip the array. A pointer is automatically a pointer
to an array.

Rather, a pointer might be a pointer to an object, or a pointer
to the first element of an array. C++ inherits this (serious)
defect from C. What he's trying to do is sensible and logical,
but it doesn't fit in with the rest of the language. The
problem is that new (MyObject*)[n] doesn't return a pointer to
an array, (type MyObject *(*)[]), but a pointer to the first
element of the array (type MyObject **). (This is also,
indirectly, the reason why we need delete[]. If the language
weren't so horribly broken in this regard, the type of the
pointer would give the compiler all the information it needs.)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,997
Messages
2,570,240
Members
46,830
Latest member
HeleneMull

Latest Threads

Top