JDN
JDN

Reputation: 519

Declaring pointer to an integer array C++

I want to declare a pointer to an integer array in the header file for my class. I have

private:
 int *theName;

and then in the constructor

theName = new int[10];

will this work? Is there another way to do this so you have a pointer to an array?

I thought int *theName created a pointer to an integer not an integer array, if this creates a pointer to an integer array how do you create a pointer to just an integer?

Also in the destructor can I call

delete theName; theName = NULL;

Will that delete theName integer array object and then point theName to null in memory?

Thanks

Upvotes: 0

Views: 17895

Answers (6)

Jerry Coffin
Jerry Coffin

Reputation: 490108

I hesitate to post this at all, but I hope it won't cause a problem.

To be pedantic: most of the other answers are wrong: what you've created is not a pointer to an array. It's a pointer to an int that refers to the initial element of the array.

I hesitate to post about it for the simple reason that this is almost certainly just a matter of having used the wrong wording in your question -- a pointer to int is almost certainly what you thought wanted, and it is what you really got.

There is, however, such as thing as a pointer to an array. It's rarely useful because when/if you do pointer math on it (including subscripting), a pointer to an array works in increments the size of the array it's pointing at. In your case you allocate 10 ints. You can use subscripting off the pointer to refer to the ints in the array, so theName[0] refers to the first int, theName[1] to the second int, and so on -- exactly what you usually want.

You might be able to make real use of a pointer to an array if you were working with (for example) an array of arrays, and wanted a pointer that would walk through that an entire row at a time, so ptr[0] was the first row, ptr[1] the second row, and so on. For example:

#include <iostream>

static const int x = 20;
static const int y = 10;

int main() {
    char data[y][x];

    auto ptr_array = &data[0];
    char *ptr_char = &data[0][0];

    std::cout << "Address of entire array: " << (void *)data << "\n";

    std::cout << "char *[0] = " << (void *)ptr_char << "\n";
    std::cout << "char *[1] = " << (void *)(ptr_char+1) << "\n";

    std::cout << "array *[0] = " << (void *)ptr_array << "\n";
    std::cout << "array *[1] = " << (void *)(ptr_array+1) << "\n";
    return 0;
}

I've changed this to work with an array of arrays of char (instead of int) to make the math a little more apparent -- sizeof(char) == 1 (by definition) so it's a little easier to work out the math. When I run this code on my machine the addresses I get are:

Address of entire array: 0047FD2C
char *[0] = 0047FD2C
char *[1] = 0047FD2D
array *[0] = 0047FD2C
array *[1] = 0047FD40

As you can see, ptr[0] holds the address of the array as a whole either way. However, with a pointer to char, ptr[1] holds an address one greater. The pointer to the array, however, holds an address 0x40 - 0x2C = 0x14 = 20 greater -- which fits with the X dimension we gave to the array (20). In other words, we really do have a pointer to an array, and pointer arithmetic (or, equivalently, subscripting) on this pointer works in terms of an entire array at a time.

I'll repeat though: at least if we ignore the fact that you almost certainly should be using an std::vector instead, the type you wanted and the type you got were both pointer to int. There such a type as pointer to array, but it's almost certainly not want you really wanted.

Upvotes: 6

cooky451
cooky451

Reputation: 3510

Yes, very nice answers with delete[] and vector and stuff, but keep this in mind: int* p is of type "pointer to int". It is indeed a pointer to a single integer. However, if you dereference it like this p[5] this is the same as saying *(p + 5). That is also how array access works. (And why you can implicitly convert an array to a pointer to its first element.) However, there is a pointer to array type. int (*p)[10] is a "pointer to array of int with size 10". However, this is not what you want. Because if now you would say p[5] it would mean *(p + 5) which would access the address p + sizeof *p * 5. But sizeof *p is sizeof int[10], so there you have the mess. (And of course, the type of p[5] would be int[10], since p is a pointer to int[10]) ;-)

Upvotes: 0

dave
dave

Reputation: 131

Yes, that will work.

You need to write delete[] theName - if you allocated with new TYPE[] then you must delete with the delete[] operator.

Setting theName to null is good form, though superfluous in the destructor, since the entire object (and thus theName) will soon cease to exist.

A better C++ approach might be to use std::vector<int>.

Upvotes: 1

dreamlax
dreamlax

Reputation: 95335

Is there another way to do this so you have a pointer to an array?

You could use std::vector. This [for the most part] can slot in whereever you are using an array and provides the following benefits:

  1. No need to worry about memory management
  2. Resizes automatically when it needs to
  3. Can continue to use array[index] syntax
  4. Can perform bounds-checking with .at() method.

If you want a pointer to the first element (to give to C-style APIs etc) you can use:

std::vector<int> vec(10);

SomeCFunction(&vec[0]);

Upvotes: 0

Ed Swangren
Ed Swangren

Reputation: 124642

Yes, that is how you would initialize the pointer. You have some problems though:

  1. You need to call delete [] on anything you allocate with new[]. Your code does not work as intended and results in UB.

  2. You need to implement a copy constructor and assignment operator. What happens if that pointer gets copied to another instance of your type? You will end up calling delete [] on it twice.

  3. Terminology nitpick:

Will that delete theName integer array object and then point theName to null in memory?

No, it sets theName to NULL. theName is a variable like any other which has a value. This variable happens to be an address, so when used as such, yes, it's value would be the numerical value of NULL, whatever that may be.

Upvotes: 0

Seth Carnegie
Seth Carnegie

Reputation: 75130

Four things:

  • One, yes that is how you make a pointer to an array. Notice that there's no difference between a pointer to an integer and a pointer to an integer array; you can think of an integer as an array of one element. You can still use x[0] if x is a pointer to an integer, and you can still use *x if x is a pointer to an array, and they work the same.

  • Secondly, you have to use delete[] theName, not delete theName. Wherever you use new you have to use delete, and wherever you use new[] you have to use delete[]. Also, it is unnecessary to set theName = NULL because after the destructor is run, you can't access theName any more anyway.

  • Thirdly, when you write a class that manages resources, you need to write a copy constructor, move constructor, copy assignment operator and move assignment operator.

  • Fourthly, unless you are just doing this as a didactic exercise, you should really use std::vector. It has many advantages and no real disadvantages. And you don't even have to write the four other constructors if you use vector.

Upvotes: 7

Related Questions