Reputation: 5563
If I write int* a = new int[5];
and then I call sizeof(a)
or sizeof(*a)
, I don't get the information I want because the array has decayed into a pointer. However, I'm wondering if there's a way we can do something like this:
int[5]* a = new int[5];
I'm pretty sure we're able to do this with stack memory but I'm not sure if there's any way to do it for heap memory, since the above will not compile. And if there isn't a way, is there a reason for not having this as a possibility?
Upvotes: 3
Views: 165
Reputation: 881383
There's no getting around the fact that C++ was originally just a front end for C and, as such, carries a fair amount of baggage from the original language. Such as many things in the <cXXX>
headers, and the behaviour of many operations, like array decay(a).
If you want a more convenient array type, C++ has such a beast in std::vector
. If you pass that around, you will not be subject to the decay you may see when using the more low-level memory allocation methods. See, for example:
#include <iostream>
#include <vector>
void someFunction (const std::vector<int> &myVec) {
std::cout << myVec.size() << std::endl;
}
int main() {
std::vector<int> myVec({ 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9, 0 });
std::cout << myVec.size() << ' ';
someFunction(myVec);
}
which outputs 13 13
, showing that the size is the same outside and inside the function (it's also the size in elements rather than bytes as given bt sizeof
, the former usually being a far more useful measure).
When mentoring or training C++ programmers, I always warn them about being a "C+" programmer, one who was raised on C and never really made the full transition to C++ (things like continuing to use raw arrays instead of vectors, rolling you own data structures when perfectly adequate ones are in the standard library, using malloc/free
or printf
, and so on).
You would be wise thinking of C and C++ as related but totally different languages, and adopting the C++ way of thinking as much as possible.
(a) Interestingly, your specific question does not have an array decaying into a pointer. The new
call actually returns a pointer directly so there's no decay involved.
Where you would see decay is in something like:
void someFunction (int x[]) {
// Pointer to first element here, size is int-pointer-size.
std::cout << sizeof(x) << std::endl;
}
:
// Array here, size is 13 * int-size.
int xyzzy[] = { 3, 1, 4, 1, 5, 9, 2, 6, 5, 3, 5, 9, 0 };
std::cout << sizeof(xyzzy) << std::endl;
someFunction(xyzzy);
Upvotes: 5
Reputation: 13040
Of course you can, via a two-dimension array, e.g.
int (*a)[5] = new int[1][5];
Note: this code is just for language-lawyer purpose and is not recommended in practice. If this is an XY problem, you should use std::vector
or std::array
instead as other answers suggested.
One of the reasons why new int[N]
returns a pointer to its first element instead of a pointer to itself like non-array new
, is to make the use of the array easier. For example, with auto a = new int[5]
, you can access the array by simple a[n]
instead of (*a)[n]
.
Upvotes: -1
Reputation: 33864
There is no way to store this information in the pointer. And there is no separate construct that will let you do this the way you want. Your options are:
const int a_size = 5; int *a = new int[a_size]
.std::vector<int> a(5); a.size()
I would highly recommend option 2. Not simply because its easier and std::vector
gives more functionality. But because the RAII style construct manages the memory for you meaning you don't need to remember to call delete[]
on the memory later. You also can't accidentally call delete
on the memory later since you might have forgotten that it is an array.
Upvotes: 3