使用size_t的负整数是否安全?

时间:2015-01-31 03:06:13

标签: c++ c++11 unsigned size-t

我刚刚看到了一些像这样的C ++代码。它使用一个条件来决定是通过std::vector前进还是后退。编译器没有抱怨,但我认为size_t是未签名的。这有危险吗?

vector<int> v { 1,2,3,4,5 };    
bool rev = true;

size_t start, end, di;
if (rev) {
    start = v.size()-1;
    end = -1;
    di = -1;
}
else {
    start = 0;
    end = v.size();
    di = 1;
}

for (auto i=start; i!=end; i+=di) {
    cout << v[i] << endl;
}

4 个答案:

答案 0 :(得分:6)

使用无符号整数(并且size_t是无符号的)已经明确定义了这种方式,并且有回绕:标准保证了这种行为,而不是有符号整数,标准不保证。< / p> 然而,这是不必要的聪明。

作为一般规则,为了避免由于对无符号的隐式包装促销而导致的问题,对于位级别的东西使用无符号整数,对数字使用有符号整数。你需要一个与size_t对应的有符号整数的地方ptrdiff_t。定义带有签名结果的n_items函数,例如

using Size = ptrdiff_t;

template< class Container >
auto n_items( Container const& c )
    -> Size
{ return end( c ) - begin( c ); }

你准备好了,不再是编译器的愚蠢警告。


而不是太聪明的代码

vector<int> v { 1,2,3,4,5 };    
bool rev = true;

size_t start, end, di;
if (rev) {
    start = v.size()-1;
    end = -1;
    di = -1;
}
else {
    start = 0;
    end = v.size();
    di = 1;
}

for (auto i=start; i!=end; i+=di) {
    cout << v[i] << endl;

做例如。

const vector<int> v { 1,2,3,4,5 };    
const bool reverse = true;  // whatever

for( int i = 0; i < n_items( v );  ++i )
{
    const int j = (reverse? n_items( v ) - i - 1 : i);
    cout << v[j] << endl;
}

答案 1 :(得分:1)

我不能说代码是多么安全,但我认为这是一种非常糟糕的风格。更好的方法是使用支持正向或反向迭代的迭代器。

例如:

std::vector<int> v = { 1, 2, 3, 4, 5 };
bool rev = true;

if (rev)
{
    for (auto itr = v.rbegin(); itr != v.rend(); ++itr)
    {
        std::cout << *itr << "\n";
    }
}
else
{
    for (auto itr = v.begin(); itr != v.end(); ++itr)
    {
        std::cout << *itr << "\n";
    }
}

答案 2 :(得分:0)

每当我需要处理签名类型时,我总是使用:

typedef std::make_signed<std::size_t>::type ssize_t; // Since C++11

...作为std :: size_t的签名替代。

我很欣赏这个问题已经有几年了,但我希望这会对别人有所帮助。归功于moodycamel::ConcurrentQueue

答案 3 :(得分:-1)

  

使用size_t的负整数是否安全?

不,这很危险。溢出。

size_t a = -1;
std::cout << a << "\n";

输出:

4294967295 // depends on the system, largest value possible here