1

assume we have an array

int arr[3];

In C++11 we can do

end(arr);

to get the boundry of arr.

and

sizeof(arr)/sizeof(arr[0])

can get the size of array.

Actually I'm from Java, and new to C++, it's intuitive to have sth. like arr.length, but why don't C++ have this nice feature? It's quite weird to use an outside function to get the size of an array.(And end function is even added after C++11, before that things are more troublesome) I guess it has sth. to do with the implementation behind array, there must be some boundry marker, just like '\0' at the end of string. Then why not make one step further to get sth. like arr.length?

Ziqi Liu
  • 2,931
  • 5
  • 31
  • 64
  • 1
    As of C++17 you can use `std::size(arr)`. – user657267 Jun 23 '18 at 13:47
  • 1
    can you also consider using [std::array](https://en.cppreference.com/w/cpp/container/array)'s [`size()`](https://en.cppreference.com/w/cpp/container/array/size)? – Joseph D. Jun 23 '18 at 13:48
  • 7
    Use `std::array` or `std::vector`. *Not* C-style arrays. Both of those containers have a `size()` member. – Jesper Juhl Jun 23 '18 at 13:49
  • Maybe its because in C and C++, when you declare the array you already know the size of the array. In traditional C and C++, programmers would use a non-dynamic identifier for the capacity (a.k.a. macro or constant integer), thus there was no need to carry the capacity of the array with the array. – Thomas Matthews Jun 23 '18 at 17:33

5 Answers5

5

C++ language arrays don't have a built-in size method because they're inherited from C and generally only offer the behavior that C gives them. C++17 provides a non-member std::size function that can compute the size of an array (of any sized container, really).

It's quite weird to use an outside function to get the size of an array.

Not everything in C++ is a member function. Best get used to that now.

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
4

I'll add another answer, although the others are right, I think they miss a core point.

Arrays of the form int arr[3]; are a remainder from the C roots of C++, and although they are fully working, they lack a lot, one of it being the capability to know their own size. They are discouraged to use at all in C++ (but are still possible, or gazillions of lines of old code would stop working!). If you write new code, you should never consider using them. There is no advantage, and many disadvantages.

The C++ way of using a simple array is the standard library template std::array<int,3> arr;. This is a safe array, which knows its own size, and can do bounds checking on access. You can use arr[i] like for an old-style array, and it has a .size() method (and many other methods).

There are many other collection types in that standard library, like vector<> (can grow and shrink during use), maps, sets, etc.

Aganju
  • 6,295
  • 1
  • 12
  • 23
  • There certainly are differences between `T[N]` and `std::array`, such as having an assignment operator. But "knowing its own size" is not such a difference. In both cases the size is encoded in the static type. As for "no advantages" to bare arrays, the fact that `sizeof(T[N]) == N * sizeof(T) && alignof(T[N]) == alignof(T)` is quite a useful one, that the Standard doesn't quite seem to guarantee for `std::array`. – Ben Voigt Jul 19 '22 at 15:44
1

EDITED:

I don't know about Java but comparing to many languages C++ is known to have the ability to be very close to the hardware. For this you use low level techniques.

For most programmers it is not necessary to use low level techniques. In fact it is not recommended at all. Consider this: (char a[6]; int i) -> a[i] == i[a]. Isn't this scary enough?

I cannot speak for hardware. Every platform is different. But imagine a sheet of paper and write there your array. Then write another one. And another one. Now some objects, strings, some unidentified binary data. Maybe some data from a different program.

Soon you will not see where it is the end of your array. C strings yes. They have \0. But ints? Isn't it \0 == 0?

Luckily we have high level programming. Many programming languages only support high level programming to prevent programmers from mistakes.

Because to wrap around the low level built in array you should use a class with a member array and member size. To make it reusable you should make it a template. Then you add lots of stuff like subscripting and iterator. It sounds like a lot of work, doesn't it? But luckily some clever people did it already. It is part of the C++11 and they are called containers. And to choose the right container? Unless you have a reason to use something else you should use the "vector".

#include <vector>
std::vector<int> arr;

Long story short. Don't use built in arrays. Use a vector.

Volt
  • 99
  • 1
  • 7
  • 2
    "*A raw array like this does not have a size.*" Then how does `std::size()` work? – Nicol Bolas Jun 23 '18 at 14:05
  • @NicolBolas , it triggers the compiler to replace it with the size; the compiler knows that still. The running executable has no way to find the size any more. – Aganju Jun 23 '18 at 14:51
  • 1
    @Aganju: I didn't ask about the "running executable", nor did the OP. Volt said that arrays don't have a size. That is untrue; they very much do have a size, one which can be queried via various means. Whether it's a static size or a runtime size is irrelevant; it has a size, so claiming that it doesn't is incorrect. – Nicol Bolas Jun 23 '18 at 15:03
  • @Nicol Bolas, you have a point there. The way I meant it was that built in array does not have a member size, nor length. Which was the question -> arr.length. I should have written built in array has no property length. – Volt Jun 23 '18 at 15:26
0

As of you are encouraged to use size on arrays.

For example, given your int arr[3] you can call: size(arr) to get 3.

I say you're encouraged, because as size can be used on either as array or a container with a size method. Allowing your template code to operate independent of whether an array or container is the type operated on.

So in this, an array could be passed as either or both arguments, just as a container could:

template <typename FROM, typename TO>
bool foo(const FROM& lhs, TO& rhs) {
    if(size(lhs) > size(rhs)) {
        return false;
    }
    copy(cbegin(lhs), cend(lhs), begin(rhs));
    return true;
}

Live Example

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
-2

In the early C++ is known as compatible to C and C doesn't has this feature

Another reason is in C++ array is not a real Object which meaning in OOP(An Object has attribute and method/function and so on)

Why arrays doesn't have a length attribute? It's a long history, C was born in 1970s, at that time all the computer's memory was very expensive and small. even the struct keyword was not joined at the early development of C language.

This Link may be helpful for you.

https://www.bell-labs.com/usr/dmr/www/chist.html

SHR
  • 7,940
  • 9
  • 38
  • 57
shaocong
  • 48
  • 7
  • 2
    "*Another reason is in C++ array is not a real Object*" ... No, arrays are real objects. They're just not like regular objects. And no, in C++, "object" doesn't mean "has attribute and method/function and so on". – Nicol Bolas Jun 23 '18 at 14:09
  • 3
    There is C code that is not valid C++ code, so the superset part is technically not true. See https://en.wikipedia.org/wiki/Compatibility_of_C_and_C%2B%2B#Constructs_valid_in_C_but_not_in_C++ (not the everyday stuff, yeah, that's why I wrote *technically*) – Aziuth Jun 23 '18 at 14:13
  • "not a real Object which meaning in OOP" – shaocong Jun 23 '18 at 14:14
  • This does not answer the question – Sebastian D'Agostino Jun 23 '18 at 14:16