简体   繁体   English

为什么我初始化数组容器的元素大于数组大小时没有出错?

[英]Why I do not get errors when I initialize an array container with more elements than the size of the array?

I noticed that when I initialize array like so: 我注意到当我像这样初始化数组时:

std::array<int,3> myarray;

myarray[0] = 9;
myarray[1] = 8;
myarray[2] = 7;
myarray[3] = 6;
myarray[4] = 5;

I do not get an error, even though I have more array elements than was defined in <int,3> 即使我有比<int,3>定义的更多的数组元素,我也不会收到错误

I am on Mac with g++ and it's C++11. 我在Mac上使用g ++,它是C ++ 11。

So I guess my question is: why is that, that there are no errors? 所以我想我的问题是:为什么这样,没有错误? Is it correct behavior? 这是正确的行为吗? Or do I expect too much form my compiler? 或者我对编译器的期望太高了?

Also what is this method of initialization called? 这个初始化方法叫做什么? Someone called it "buggy construction". 有人称之为“越野车建筑”。 I think they meant it as a joke though. 我认为他们认为这只是一个笑话。

PS I understand that this method is undesirable . PS我明白这种方法是不可取的

EDIT: Some folks suggested that my question is a duplicate . 编辑:有些人建议我的问题是重复的 But according to the best answer from Vlad it does not seem to be. 但根据弗拉德的最佳答案,似乎并非如此。 According to Vlad my question is about operator overloading and not C style array range. 根据Vlad我的问题是关于运算符重载而不是C风格的数组范围。 I have to trust his expertise and what he said just makes sense. 我必须相信他的专业知识以及他所说的才有意义。

It is undefined behavior . 这是未定义的行为 The compiler does not have to warn you about undefined behavior. 编译器不必警告您未定义的行为。

If you really want to know when you have gone out of the bounds of the array then use at() which will throw an exception. 如果你真的想知道什么时候你已经超出了数组的边界,那么使用at()会抛出异常。

In general the compiler does not check indices used in the subscript operator for arrays. 通常,编译器不检查数组的下标运算符中使用的索引。

As for the class std::array then the subscript operator is overloaded and looks like for example 至于类std::array那么下标运算符会被重载,例如看起来像

T & operator []( size_t i );

So this record 所以这个记录

myarray[4] = 5;

is equivalent to 相当于

myarray.operator []( 4 ) = 5;

that syntactically is correct. 语法上是正确的。 So the compiler does not have a reason for issueing an error. 因此编译器没有理由发出错误。

... why is that, that there are no errors? ......为什么这样,没有错误? Is it correct behaviour? 这是正确的行为吗?

Well, the code invokes undefined behaviour . 好吧, 代码调用未定义的行为 As you have observed it, it could do nothing apparent, or it could also throw a runtime error. 正如您所观察到的那样,它不会显而易见,或者它也可能引发运行时错误。

In these situation there are generally three types of errors you can run into; 在这种情况下,通常会遇到三种类型的错误;

  • Compile time array initialisation errors 编译时间数组初始化错误
  • Run time out of bounds error 运行超出范围错误
  • Undefined behaviour 未定义的行为

Compile time array initialisation errors 编译时间数组初始化错误

When initialising an array with more elements that the size of the array, the compiler can and does issue an error. 当使用更多元素初始化数组时,编译器可以并确实发出错误。 It has sufficient information to diagnose these and as such, it does. 它有足够的信息来诊断它们,因此它确实如此。

std::array<int,3> my_array = {1, 2, 3, 4, 5}; // compiler error

Run time out of bounds error 运行超出范围错误

When indexing into the std::array (and other standard library containers), there are generally two forms; 索引到std::array (和其他标准库容器)时,通常有两种形式; using the index operator [] or using a member method at() . 使用索引运算符[]at()使用成员方法 The index operator is generally implemented for performance and hence won't do any bounds checking, the at() on the other hand does do bounds checking and will throw an exception if the indexed element is larger that the array size. 索引运算符通常是为了执行而实现的,因此不会进行任何边界检查,另一方面, at()会进行边界检查,如果索引元素大于数组大小,则抛出异常。

The compiler generally does not have sufficient information to diagnose these conditions as errors, hence it won't - but you might get a warning. 编译器通常没有足够的信息将这些条件诊断为错误,因此它不会 - 但您可能会收到警告。 Other tools make exist to catch these errors during the build (as could be possible in the sample given). 存在其他工具以在构建期间捕获这些错误(在给出的样本中可能是这样)。

Undefined behaviour 未定义的行为

This is basically the alternate situation to the bounds check. 这基本上是边界检查的替代情况。 If you index an element out of the bounds of the error, the behaviour is undefined. 如果将元素索引到错误的边界之外,则行为未定义。 It may result in a segmentation fault (or access violation), or it may not throw any runtime error or exception. 它可能导致分段错误(或访问冲突),或者它可能不会抛出任何运行时错误或异常。

If you implement it using Microsoft's GSL span it will fail fast as promised by Neil Macintosh. 如果使用Microsoft的GSL span实现它,它将像Neil Macintosh所承诺的那样快速失败。 So maybe not desirable in either case but with this approach the program terminates and indicates an issue worth investigating. 因此,在任何一种情况下可能都不可取,但通过这种方法,程序终止并指出值得研究的问题。

array<int, 3> a;
a[0] = 0;
a[1] = 1;
a[2] = 2;
a[3] = 3;
a[4] = 4;

for (auto& i : a) {
    cout << i << endl;
}

gsl::span<int, 3> s = a;
s[0] = 10;
s[1] = 11;
s[2] = 12;
//    s[3] = 13;

for (auto& i : s) {
    cout << i << endl;
}

outputs 输出

0
1
2
10
11
12

Uncommenting s[3] = 13 compiles but fails. 取消注释s [3] = 13编译但失败。

0
1
2
libc++abi.dylib: terminating
zsh: abort      ./gsl_span

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 当我尝试在大小为 4 或更大的数组中仅输入三个元素时,为什么无法获得输出? - Why am I unable to get the output when I try to enter only three elements in an array of size four or more? 为什么在尝试初始化数组时出现错误? - Why I get error when I try to initialize an array? 为什么我必须初始化一个数组? - Why do i have to initialize an array? 数组中出现大于 size/2 的元素 - Elements in an array occurring more than size/2 如何在 C++ class 中初始化可变大小数组? - How do I initialize a variable size array in a C++ class? 初始化大小为变量的数组时会发生什么? - What happens when I initialize an array having the size as a variable? 为什么需要在分配时使用()初始化动态分配的数组? - Why do I need to initialize dynamically allocated array at allocation time with ()? 当我尝试将一个双精度数分解为一个数组作为元素时,为什么我会得到一个偏移量,阻止我获得最后一位数字? - When I try to decompose a double number into an array as elements, why do I get an offset preventing me from getting the last digit? 为什么我的数组打印的比我想要的多? - Why does my array print more than I want? 创建对象时如何初始化数组? - How do I initialize an array when an object is created?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM