C++ 中数组的元素计数
假设我有一个数组 arr
。以下什么时候不会给出数组元素的数量:sizeof(arr) / sizeof(arr[0])
?
我只能处理一种情况:数组包含属于数组类型的不同派生类型的元素。
我是对的吗?还有(我几乎肯定一定有)其他类似的情况吗?
抱歉问这个小问题,我是一名 Java 开发人员,而且对 C++ 还很陌生。
谢谢!
Let's say I have an array arr
. When would the following not give the number of elements of the array: sizeof(arr) / sizeof(arr[0])
?
I can thing of only one case: the array contains elements that are of different derived types of the type of the array.
Am I right and are there (I am almost positive there must be) other such cases?
Sorry for the trivial question, I am a Java dev and I am rather new to C++.
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(14)
从 C++17 开始,您还可以使用标准化的自由函数:
std::size(container)
将返回该容器中的元素数量。例子:
Since C++17 you can also use the standardized free function:
std::size(container)
which will return the amount of elements in that container.example:
C++ 中的数组与 Java 中的数组有很大不同,因为它们完全是非托管的。编译器或运行时不知道数组的大小。
如果在声明中定义了大小,则仅在编译时才知道该信息:
在这种情况下,sizeof(array) 为您提供正确的大小。
但是,如果您使用指针作为数组,则“数组”将只是一个指针,并且 sizeof 不会为您提供有关数组实际大小的任何信息。
STL 提供了很多模板,允许您拥有数组,其中一些具有大小信息,一些具有可变大小,而大多数模板具有良好的访问器和边界检查。
Arrays in C++ are very different from those in Java in that they are completely unmanaged. The compiler or run-time have no idea whatsoever what size the array is.
The information is only known at compile-time if the size is defined in the declaration:
In this case, sizeof(array) gives you the proper size.
If you use a pointer as an array however, the "array" will just be a pointer, and sizeof will not give you any information about the actual size of the array.
STL offers a lot of templates that allow you to have arrays, some of them with size information, some of them with variable sizes, and most of them with good accessors and bounds checking.
给定一个数组
arr
,在任何情况下,sizeof(arr) / sizeof(arr[0])
的值都不是元素的计数,通过数组和sizeof
的定义。事实上,甚至直接提到了它(§5.3.3/2):
强调我的。除以元素的大小
sizeof(arr[0])
,得到 n。There are no cases where, given an array
arr
, that the value ofsizeof(arr) / sizeof(arr[0])
is not the count of elements, by the definition of array andsizeof
.In fact, it's even directly mentioned (§5.3.3/2):
Emphasis mine. Divide by the size of an element,
sizeof(arr[0])
, to obtain n.不,这仍然会产生正确的值,因为您必须将数组定义为单一类型的所有元素或指向类型的指针。无论哪种情况,数组大小在编译时都是已知的,因此 sizeof(arr) / sizeof(arr[0]) 始终返回元素计数。
以下是如何正确使用此功能的示例:
我将在此处进一步说明何时正确使用此功能。你不会经常使用它。当您想要专门定义一个数组时,它非常有用,这样您就可以向其中添加元素,而无需稍后更改大量代码。它是一个主要用于维护的结构。典型的例子(无论如何,当我想到它时;-)正在为某个程序构建一个命令表,您打算稍后添加更多命令。在此示例中,要维护/改进您的程序,您所需要做的就是向数组添加另一个命令,然后添加命令处理程序:
No that would still produce the right value because you must define the array to be either all elements of a single type or pointers to a type. In either case the array size is known at compile time so sizeof(arr) / sizeof(arr[0]) always returns the element count.
Here is an example of how to use this correctly:
I'll go one further here to show when to use this properly. You won't use it very often. It is primarily useful when you want to define an array specifically so you can add elements to it without changing a lot of code later. It is a construct that is primarily useful for maintenance. The canonical example (when I think about it anyway ;-) is building a table of commands for some program that you intend to add more commands to later. In this example to maintain/improve your program all you need to do is add another command to the array and then add the command handler:
MSVC 中的 _countof(my_array)
C++ 中数组的元素是对象,而不是指针,因此不能将派生类型对象作为元素。
正如上面提到的, sizeof(my_array) (也像 _countof() )将仅在数组定义的范围内工作。
_countof(my_array) in MSVC
Elements of an array in C++ are objects, not pointers, so you cannot have derived type object as an element.
And like mentioned above, sizeof(my_array) (like _countof() as well) will work just in the scope of array definition.
首先,您可以使用
std::vector
< 来规避该问题/a> 而不是数组。其次,如果将派生类的对象放入超类的数组中,您将遇到切片,但好消息是,您的公式将起作用。 C++ 中的多态集合是使用指针实现的。这里有三个主要选项:boost 的集合: :shared_ptr
First off, you can circumvent that problem by using
std::vector
instead of an array. Second, if you put objects of a derived class into an array of a super class, you will experience slicing, but the good news is, your formula will work. Polymorphic collections in C++ are achieved using pointers. There are three major options here:boost::shared_ptr
在
arr
实际上不是数组(而是指向初始元素的指针)的上下文中。其他答案解释了这是如何发生的。这是不可能发生的(从根本上讲,这与 Java 数组不能很好地与泛型配合使用的原因相同)。该数组是静态类型的;它保留了适合特定类型(基本类型)大小的内存“槽”。
C++ 数组不是一流对象。您可以使用 boost::array 使它们的行为更像 Java 数组,但请记住,您仍然拥有值语义而不是引用语义,就像其他所有内容一样。 (特别是,这意味着您不能真正声明类似于 Java 中的
Foo[]
类型的变量,也不能用另一个不同大小的数组替换数组;数组大小是type。)在此类中使用.size()
,而在 Java 中则使用.length
。 (它还提供了为 C++ 迭代器提供常用接口的迭代器。)In contexts where
arr
is not actually the array (but instead a pointer to the initial element). Other answers explain how this happens.This cannot happen (for, fundamentally, the same reason that Java arrays don't play nicely with generics). The array is statically typed; it reserves "slots" of memory that are sized for a specific type (the base type).
C++ arrays are not first-class objects. You can use boost::array to make them behave more like Java arrays, but keep in mind that you will still have value semantics rather than reference semantics, just like with everything else. (In particular, this means that you cannot really declare a variable of type analogous to
Foo[]
in Java, nor replace an array with another one of a different size; the array size is a part of the type.) Use.size()
with this class where you would use.length
in Java. (It also supplies iterators that provide the usual interface for C++ iterators.)使用 Microsoft“_countof(array)”宏。 Microsoft Developer Network 的链接对此进行了解释,并提供了一个示例来演示“sizeof(array)”和“_countof(array)”宏之间的区别。
Microsoft 和“_countof(array)”宏
Use the Microsoft "_countof(array)" Macro. This link to the Microsoft Developer Network explains it and offers an example that demonstrates the difference between "sizeof(array)" and the "_countof(array)" macro.
Microsoft and the "_countof(array)" Macro
看来,如果您知道数组中元素的类型,您也可以通过
sizeof
来利用它。It seems that if you know the type of elements in the array you can also use that to your advantage with
sizeof
.如果您不能使用允许使用
std::size(container)
的 C++17,您可以轻松地将自己的通用sizeofArray
模板函数实现为一个 -班轮:在这里测试:http://cpp.sh/8tio3
If you can not use C++17, which allows to use
std::size(container)
, you can easily implement your own genericsizeofArray
template function as a one-liner:test it here: http://cpp.sh/8tio3
当且仅当
arr
是一个 C 数组(type[size]
;函数参数除外!)、对 C 数组的引用(>type(&)[size]
) 或指向 C 数组的指针 (type(*)[size]
)。注意对于当前的 C++ 标准,您应该使用
std::size
或std::ssize
来代替!在C++17中,您可以使用
std::size
:在C++20中,您可以另外获得使用
std::ssize
得到有符号值:另请注意,C++ 不幸地从 C 继承,C 数组永远不会按值(深层复制)传递给函数。
与此相同,
因此您会丢失
a
是一个数组以及它有多少元素的信息。3
被编译器完全忽略!如果要保留数据类型(包括数组元素计数),可以使用指针或对 C 数组的引用:
如果要使用数组按值调用来调用函数,可以使用 C++ 数组(
std::array
) 来自 C++ 标准库:It will work if and only if
arr
is a C-Array (type[size]
; except for function parameters!), a reference to a C-Array (type(&)[size]
) or a pointer to a C-Array (type(*)[size]
).Note you should use
std::size
orstd::ssize
instead with current C++-Standards!In C++17 you can use
std::size
:In C++20 you can additionally get a signed value by using
std::ssize
:Also note that C++ unfortunately inherited from C that C-Arrays are never passed by value (deep copy) to functions.
is the same as
so you loose the information that
a
is an array and with this, how much elements it had. The3
is completely ignored by the compiler!If you want to preserve the datatype (including the array element count), you can use a pointer or a reference to an C-Array:
If you want to call functions with Arrays call-by-value, you can use C++-Arrays (
std::array
) from the C++ standard library:确定数组中有多少个数字。
Determine how many numbers are in your array.
我知道这是一个老话题,但是像 while 循环这样的简单解决方案怎么样?
我知道这比 sizeof() 慢,但这是数组计数的另一个例子。
I know is old topic but what about simple solution like while loop?
I know that is slower than sizeof() but this is another example of array count.
我经常看到新程序员这样做的一件事:
新程序员认为
count
的值将是 10。但这是错误的。即使这是错误的:
这都是因为一旦将数组传递给任何这些函数,它就会变成指针类型,因此
sizeof(arr)
将给出<的大小em>指针,而不是数组!编辑:
以下是一种优雅的方法,您可以将数组传递给函数,而不让它衰减为指针类型:
One thing I've often seen new programmers doing this:
So new programmers think the value of
count
will be 10. But that's wrong.Even this is wrong:
It's all because once you pass an array to any of these functions, it becomes pointer type, and so
sizeof(arr)
would give the size of pointer, not array!EDIT:
The following is an elegant way you can pass an array to a function, without letting it to decay into pointer type: