我用a替换了一个旧样式数组std::array,但后来我意识到编译器(至少是MSVC)正在进行较少的绑定检查.考虑以下代码:
double myArray[10];
myArray[11] = 3.0;
std::array<double,10> myStdArray;
myStdArray[11] = 3.0;
Fo myArray报告了一个警告:
警告C4789:大小为80字节的缓冲区'myArray'将被溢出; 从偏移量88开始写入8个字节
因为myStdArray,根本没有报告任何警告.
它是编译器中的"错误"还是std::array实现方式不允许报告此类警告?如果是这样,值得使用std::array,这似乎不太安全......
小智 7
myArray[11] 是编译器知道的语言内置功能,以及编译器可以警告的功能.
myStdArray[11]是一个简短myStdArray.operator[](11)的函数调用,11它在参数类型的范围内很好.警告这需要查看operator[]函数体,这通常只有在函数内联时才会发生.
此外,厂商扩展可能会使myStdArray.operator[](11)明确界定,例如,作为在调试模式下中止程序,并在这样的实现是非常困难的获取有用的编译时警告.
但是,通过这种扩展,增加的运行时安全性仍可能超过缺少编译时警告.
std::get如果您的访问超出范围,您可以使用以获得保证的错误.当然,必须在编译时知道索引.
std::array<double,10> myStdArray;
std::get<9>(myStdArray) = 3.0; // ok
std::get<11>(myStdArray) = 3.0; // error
关于你问题的另一部分:这可能是我的猜想,但标准库应该被认为是"神奇的",就像编译器知道它的合同一样,没有什么能使它无法进行事实检查.
通过以下示例可以很容易地证明这一点.clang和gcc都memset支持直接写入以下函数的调用:
void zero_int(int* ptr)
{
  memset(ptr, 0, sizeof(int));
}
因此,据我所知,除了可能的实现难度/成本之外,没有什么能阻止编译器在代码中发出警告.