开发者

C++ -- Pointers to Arrays -- Arrays of Pointers

I notice this has caused confusion for several people, but after reading a couple of posts on here and the cplusplus tutorial my brain is still scrambled.

Suppose I have the following variables in a header file -

int numberOfLinePoints;
D3DXVECTOR3* line;   //confused as to what it is

Then in the implementation C++ file I initialize them as follows -

//both initialized in constructor
numberOfLinePoints = 25;
line = new D3DXVECTOR3[numPoints];   //array of pointers?

What does my line variable now represent?

As far as I can tell from reading links on stackoverflow it should represent an array of pointers. I then read the following however...

(1) Pointers for Beginners

...where (A) arrays of pointers, and (B) pointers to arrays, are both discussed. This left me confused once again as they both seem to work similarly.

The fact that I define my pointers in a seperate location to where I allocate (correct?) them seems to be where my confusion stems from. Am I correct that this is an array of pointers to D3DXVECTOR3 objects?

To finish - if variable line holds information about one line segment, how would I create an array of line s开发者_开发知识库egments? I currently have the following -

//HEADER FILE
int numberOfLineSegments;
D3DXVECTOR3** lineCollection;   //array of pointers - each of which
                                //points to an array of pointers?
//CPP FILE
numberOfLineSegments = 8;                            //constructor
for(i = 0; i < numberOfLineSegments; i++)            //initialization
{                                                    //and allocation  CORRECT?
   lineCollection[i] = new D3DXVECTOR*[numPoints];   //of memory for     Y/N
}                                                    //lineCollection

VOID createLineSegments(startPoint, endPoint) //could return array instead
{
//pseudo to generate one line segment
while != numberOfLinePoints
line[sentinel++] = interpolate(startPoint, endPoint, time_T)

//pseudo to generate array of line segments
while != numberOfLines
lineCollection[sentinel++] = line
}

Any help is much appreciated.


Your first example:

int numberOfLinePoints;
D3DXVECTOR3* line;   //confused as to what it is

Declares a simple pointer to a D3DXVECTOR3. A pointer can be initialized in two ways. First:

line = new D3DXVECTOR3;

This creates a single D3DXVECTOR3 and makes line point to that object. Second:

line = new D3DXVECTOR3[numberOfLinePoints];

This creates an array of D3DXVECTOR3s and makes line point to the first element of that array. You can then use pointer arithmetics to access other elements in that array.

If you declare you pointer as double pointer:

D3DXVECTOR3** line;

You simply create another level of indirection.


int numberOfLinePoints;
D3DXVECTOR3* line;   //confused as to what it is
//both initialized in constructor
numberOfLinePoints = 25;
line = new D3DXVECTOR3[numPoints];   //array of pointers?

line is an array of D3DXVECTOR3. It would be an array of pointers if D3DVECTOR3 is itself a pointer, however. Since I don't know the C++ D3D headers very well, I'm not sure.

D3DXVECTOR3** lineCollection;

Is an array of pointers, each pointer likely being a pointer to a line (that is, an array of D3DXVECTOR3).

You have two options. Memorywise, the best would be to set each entry in lineCollection to just point to the corresponding line. This is safe if you either know the lines aren't going to change (and aren't going to be freed), or if they do change you want the changes to be reflected immedaitely inside your collection.

The other option would be to create a new array for each entry in lineCollection, and copy the points from each line into this new array.

There is no correct answer, it depends on the functionality you want.


(Attempting to answer the first part of the question as succinctly as possible without introducing other issues.)

C++ (and C) uses pointers to a single item in an array as a handle for the full array. However, some pointers don't point to items in an array! You have to make the distinction between points-to-single-item and points-to-item-in-array yourself.

int length = 8;
D3DXVECTOR3* line = new D3DXVECTOR3[length];

The new[] operator returns a pointer to the first item in the array it allocates, and this assigns that value to line. Notice that because pointers don't make the distinction of single-item vs. item-in-array:

  • you have to store the length separately
  • you have to be careful you use correct indices with pointers ("line" above)
  • you are better off using a "real" container type, such as:
    • std::deque, std::vector, etc.
    • std::tr1::array (aka boost::array)

(The last bullet point doesn't mean you never use pointers, you just don't use them when these containers are more appropriate.)


D3DXVECTOR3 line; // Line is a D3DXVECTOR3
D3DXVECTOR3 * line; // Line is EITHER a pointer to D3DXVECTOR3 OR an
                    // array of D3DXVECTOR3
D3DXVECTOR3 ** line; // Line is an array of pointers to D3DXVECTOR3 OR
                     // an array of array of D3DXVECTOR3

This is because an array is no specific structure in memory. It is just a bunch of D3DXVECTOR3 in a row. So pointing to the first element, and you get access to all of the others.

So, having

D3DXVECTOR3** lineCollection; // An array of pointers OR an array of array!
new D3DXVECTOR[numPoints]; // A pointer to an array of D3DXVECTOR
lineCollection[i] // A pointer to an array

You initialize it by:

lineCollection[i] = new D3DXVECTOR[numPoints]; // No extra *

Yet: try to use the STL (like std::vector) instead of ugly C/Java style arrays. If you can, avoid declaring on the heap (using 'new'), but rather declaring on the stack:

D3DXVECTOR a, b, c; // a, b, and c ARE D3DXVECTOR, not pointers
std::vector<D3DXVECTOR> lines;
lines.push_back(a);
lines.push_back(b);
lines.push_back(c);

// equivalently: (you can push_back without temporaries)
std::vector<D3DXVECTOR> lines;
lines.push_back(D3DXVECTOR());
lines.push_back(D3DXVECTOR());
lines.push_back(D3DXVECTOR());

This will avoid manual memory management; it's more readable. You might not be able to always use that comfort (the way your code is organized). And if someone says something about performances, for now, don't worry. First get something working without segfaults nor memory leaks.


line = new D3DXVECTOR3[numPoints];

line holds the memory address of the first element of the array of D3DXVECTOR3.

I.e. line is a pointer to the first element of the array.

This article should clarify it.


Just look at this simple example :

case 1:

int *p = new int [N];

Here p is pointer to array of N integers and p stores starting address of the array.

case 2:

int **p = new int *[N]; //p is a pointer to pointers holding integers used for 2D array.


for(int i=0 ; i<N ; i++)
{

    p[i] = new int [N]; // each element is pointer to array of integers.

}

It is applicable to all kinds of user defined types.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜