使用size_t来移动vector index安全吗?

Is it safe to use size_t to shift vector index?

本文关键字:index 安全 vector 移动 size 使用      更新时间:2023-10-16

我更喜欢使用size_t来处理向量索引。但当转移指数时,安全吗?例如,

size_t n = 10000000;
vector<int> v(n);
size_t i = 500000;
size_t shift = 20000;
int a = v(i - (-1) * shift); // Is this ok? what is `(-1) * shift` type, size_t?
int b = v(-shift + i); // Is this ok? what is `-shift` type, size_t?

unsigned数量为无效操作。c++ 11第5.3.2节:

无符号数的负数是通过减去它来计算的2^n的值,其中n是升序的位数操作数。结果的类型为提升操作数的类型。

所以,这是"安全的",因为这是定义行为。

size_t(-1)相乘是安全的,它将size_t的最大值包裹起来,因为size_t是无符号类型。所以(-1) * shiftstd::numeric_limits<size_t>::max-shift+1是一样的

当然,你指的是v[...]而不是v();std::vector没有operator(int)

总之,根据经验,

#include <iostream>
using namespace std;
int main(){
    unsigned foo = 1;
    cout<<(-1)*foo<<'n';
    cout<<-foo<<'n';
    cout<<foo*(-1)<<'n';
    cout<<static_cast<int>(-foo)<<'n';
    cout<<static_cast<int>(foo)*-1<<'n';
}

收益率:

4294967295
4294967295
4294967295
-1
-1

因此,一个反的unsigned或一个unsigned乘以-1通过环绕其最大值而溢出(这也应该是理论上的行为)。

对于将size_t传递给http://en.cppreference.com/w/cpp/container/vector/operator_at,如果碰巧std::vector<T>::size_type不是size_t(不太可能但可能),在你的向量的size()的边界内传递size_t应该是安全的,不会导致UB,因为size_t必须足够大,以索引任何大小的数组。