std::数组。为什么 "at(-2) "没有警告或错误?

问题描述 投票:0回答:2

书上说 std::array 比其他赋值方法更安全、更简单。

这是我的代码。

#include<iostream>
#include<array>
using namespace std;

int main()
{
    array<int, 5> a = {1, 2, 3, 4, 5};
    a.at(-2) = 100;
    cout << a[-2] << endl;
    return 0;
}

为什么这段代码中没有警告或错误?

c++ c++11 compiler-warnings stdarray
2个回答
2
投票

at 成员函数进行运行时检查,而 operator[] 不进行检查(这是有意设计的)。

你可以通过使用 get:

#include <array>
using namespace std;

int main()
{
    array<int, 5> a = {1, 2, 3, 4, 5};
    get<1>(a) = 100;  // ok
    get<-2>(a) = 100; // error
    get<5>(a) = 100;  // error
}

1
投票

std::array::at() 接受一个参数: size_type 通常是根据一些 unsinged 类型 例如 std::size_t unsigned long.

实际参数 -2signed int 属于 默化size_type 同时传递给 at() 并成为有效的 size_type 数;但是,只能是一个绕口令。见 例子.

默认情况下,你不会收到隐式转换的编译器警告错误。你必须寻找你的编译器选项,如 海合会的 -Wconversion, Wsign-conversion等来启用这些设置。在你的情况下,在GCC上。-Wsign-conversion 会对这些转换提出警告;并且,结合着 -Werror这些警告会变成错误。

观察编译器输出的代码,编译器的标志是 -std=c++11 -Werror -Wsign-conversion ():

编译器输出。

<source>: In function 'int main()':

<source>:6:10: error: unsigned conversion from 'int' to 'std::array<int, 5>::size_type' {aka 'long unsigned int'} changes value from '-2' to '18446744073709551614' [-Werror=sign-conversion]

    6 |     a.at(-2)=100;

      |          ^~

<source>:7:13: error: unsigned conversion from 'int' to 'std::array<int, 5>::size_type' {aka 'long unsigned int'} changes value from '-2' to '18446744073709551614' [-Werror=sign-conversion]

    7 |     cout<<a[-2]<<endl;

      |             ^~

cc1plus: all warnings being treated as errors

这是另一个 例子 ,模拟了同样的事情。


而且,在 at(),通过的参数将根据数组大小进行验证。这里,你会得到一个类型为 std::out_of_range 所述 文件:

如果: pos 不在容器的范围内,就会出现类型为 std::out_of_range 被抛出。

如果你愿意的话,你可以看看你的编译器提供的实现。

而且,当你使用一个无效的索引与 下标运算符 [] 例如 a[-2] 哪儿 -2size_type 转换后返回一个环绕的值,结果将是一个越界访问,并将导致一个 未定义的行为.

希望这个解释能帮到你


0
投票

访问无效的 std::array 含有 .at 将导致异常处理程序抛出运行时错误,无论你是在发布版还是调试版中编译和运行它。

只有当你使用成员访问操作符的时候,你才不会看到错误。[] 就像你在发布模式下的例子一样,在调试模式下,你只会在编译和运行后得到越界的错误。

cout<<a[-2]<<endl;

在调试模式下,你只有在编译和运行后才会得到越界的错误。在发布模式下,这是未定义的行为。

这也是为什么使用 .at 建议不要直接使用 [] 运营商。

© www.soinside.com 2019 - 2024. All rights reserved.