我用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
似乎不太安全......
答案 0 :(得分:7)
如果您的访问超出范围,您可以使用std::get
来获得有保证的错误。当然,必须在编译时知道索引。
std::array<double,10> myStdArray;
std::get<9>(myStdArray) = 3.0; // ok
std::get<11>(myStdArray) = 3.0; // error
关于你问题的另一部分:这可能是我的猜想,但应该考虑标准库&#34;魔法&#34;在编译器知道其合同的方式中,没有任何东西使其无法进行事实检查。
以下示例很容易证明这一点。 clang和gcc都忽略memset
调用,支持直接写入以下函数:
void zero_int(int* ptr)
{
memset(ptr, 0, sizeof(int));
}
所以,据我所知,除了潜在的实施难度/成本之外,没有什么能阻止编译器在代码中发出警告。
答案 1 :(得分:7)
myArray[11]
是语言内置功能,编译器知道这些功能以及编译器可以警告的功能。
myStdArray[11]
是myStdArray.operator[](11)
的缩写,11
是一个函数调用,其中operator[]
在参数类型的范围内。警告这需要查看myStdArray.operator[](11)
的函数体,这通常只有在函数内联时才会发生。
此外,供应商扩展程序可能会使var orderSchema = mongoose.Schema({
user :{
type : Schema.Types.ObjectId, ref: "User"
},
name : {
type : String
},
phone : {
type : String
},
residence : {
type : String
},
street :{
type : String
},
building :{
type : String
},
status :{
type : String
},
paymentMode :{
type : String
},
cart :{
type : Object
}
});
定义明确,例如在调试模式下中止程序,在这种实现中,非常很难得到有用的编译时警告。
但是,通过此类扩展,增加的运行时安全性仍可能超过编译时警告的缺失。