1

What are the differences between the following notations?

int * arrayA = new int[5];
int arrayB[5];

I am aware that the first line would return a pointer type whereas the second line returns an int[] type — but what happens inside? How would I programmatically determine the element count of arrayA?

5
  • 7
    int [5] arrayB; is not legal, you mean int arrayB[5]; Commented Nov 19, 2013 at 16:43
  • @john: Whoops, fixed. Commented Nov 19, 2013 at 16:45
  • You cannot determine the length of an array at runtime... In C, unlike in java, arrays do not keep track of their own lengths. You have to keep track of the length yourself. Commented Nov 19, 2013 at 16:45
  • @Alderath In C++, what you say only applies to dynamically allocated arrays. Commented Nov 19, 2013 at 16:48
  • 3
    If you want to programmatically determine the size, use std::vector. In fact, just use std::vector, regardless. You'll find it much easier. Commented Nov 19, 2013 at 16:49

4 Answers 4

4

The difference is that arrayB is an array with automatic storage duration (~ on the stack if it's a local variable), while arrayA is a pointer to the first element of an array with dynamic storage duration (~ on the heap).

The element count of arrayB can be determined like this:

template <class T, size_t N>
size_t getElementCount(T (&)[N]) { return N; }

int main() {
  assert(getElementCount(arrayB) == 5);
}

The element count of arrayA can not be determined. It's not stored in any place accessible to your program.

Sign up to request clarification or add additional context in comments.

1 Comment

The element count for arrayB can also be determined with a sizeof(arrayB)/sizeof(arrayB[0]) operation (as long as arrayB has not been decayed). The size of arrayA is known when you create it, so it should not need to be "determined".
3

The first allocates the memory dynamically. The lifetime of the array lasts until you explicitly free it (delete [] arrayA;). In practice, there is never any reason to do this; just use std::vector<int> (so you don't have to worry about the delete).

The second creates an array as a local variable. It will cease to exist when the variable goes out of scope. If for some reason you cannot use std::vector, then prefer this solution.

With regards to the size of the array: in the first case, it's up to you to manage it. As far as the language is concerned, all you have is a pointer. In the second case, you can get the size using the standard functions std::end( arrayA ) - std::begin( arrayA ) (at least in C++11). Or if you're passing it to another function, you can pass it by reference; if the other function is a template (e.g. template <size_t N> void func( int (&array)[N] )), the compiler will instantiate it with the correct size. If it isn't a template (e.g. void func( int (&array)[5] )), the compiler will complain if the size is not correct.

2 Comments

+1: The arrayB replacement would be better served by std::array, though.
@ZacHowland Probably, at least in his scenario. (About the only time I use anything but std::vector is when I want fully static initialization with the compiler counting the initializers. Which is the one thing that std::array doesn't support.)
3

I think you mean

int arrayB[5];

instead of

int [5] arrayB;

because the last one is not a legal C++ declaration. Such a declaration is used in C#.

In this case

int * arrayA = new int[5];

an unnamed array is created in the heap and the address of the first element of the array is assigned to pointer arrayA. Variable arrayA knows nothing about how many elements you allocated. For example these two variables below have the same type

int *array1 = new int[5];
int *array2 = new int[10];

In the second case

int arrayB[5];

variable arrayB denotes an array of 5 elements of type int. it has type int[5] and knows that it has 5 elements. For example int[5] and int[10] are two different types.

1 Comment

Thanks Vlad, I already corrected the notation in my original post.
3

What are the differences between the following notations?

The first allocates a dynamic array and gives you a pointer to it. You will need to delete the array (delete [] p) when you no longer need it, otherwise the memory will leak. It's usually best not to use raw pointers to manage dynamic resources, as it's tricky to make sure it's correctly deleted. Prefer RAII classes such as std::vector<int> to manage the resource automatically.

The second declares an array in whatever scope the declaration appears in. If this is inside a function, it has automatic storage duration and will be destroyed automatically when it goes out of scope. If it's outside a function, it has static storage duration and will be destroyed automatically at the end of the program.

How would I programmatically determine the element count of arrayB?

In the C manner:

size_t arrayB_size = sizeof arrayB / sizeof arrayB[0];

or in the C++ manner:

template <typename T, size_t N> size_t array_size(T(&)[N]) {return N;}
size_t arrayB_size = array_size(arrayB);

Note that you can't determine the size of the dynamic array - that information is lost. The first style would give a bogus result (based on the size of a pointer rather than the array), and the second would fail to compile. That's another reason to perfer vector, which knows its size.

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.