对于大多数签名/未签名警告,可接受修复? [英] acceptable fix for majority of signed/unsigned warnings?

查看:183
本文介绍了对于大多数签名/未签名警告,可接受修复?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我自己深信,在一个项目中,我正在处理有符号整数是大多数情况下的最佳选择,即使其中包含的值不能为负。 (更简单的反向循环,更少的错误机会等,特别是对于整数只能保持0和之间的值,例如,20)。

I myself am convinced that in a project I'm working on signed integers are the best choice in the majority of cases, even though the value contained within can never be negative. (Simpler reverse for loops, less chance for bugs, etc., in particular for integers which can only hold values between 0 and, say, 20, anyway.)

大多数出现错误的地方是std :: vector的简单迭代,这往往是过去的一个数组,后来更改为std :: vector。所以这些循环一般看起来像这样:

The majority of the places where this goes wrong is a simple iteration of a std::vector, often this used to be an array in the past and has been changed to a std::vector later. So these loops generally look like this:

for (int i = 0; i < someVector.size(); ++i) { /* do stuff */ }

因为这种模式经常使用,编译器警告垃圾邮件关于这种比较签名和无符号类型往往隐藏更多有用的警告。注意,我们绝对没有INT_MAX元素以上的向量,并且注意到,现在我们使用两种方法来修复编译器警告:

Because this pattern is used so often, the amount of compiler warning spam about this comparison between signed and unsigned type tends to hide more useful warnings. Note that we definitely do not have vectors with more then INT_MAX elements, and note that until now we used two ways to fix compiler warning:

for (unsigned i = 0; i < someVector.size(); ++i) { /*do stuff*/ }

这通常是可行的,但如果循环包含任何代码,如'if(i-1> = 0)...'等,可能会无声地中断。

This usually works but might silently break if the loop contains any code like 'if (i-1 >= 0) ...', etc.

for (int i = 0; i < static_cast<int>(someVector.size()); ++i) { /*do stuff*/ }

此更改没有任何副作用,但它确实使循环更少的可读性。 (更多打字。)

This change does not have any side effects, but it does make the loop a lot less readable. (And it's more typing.)

所以我想出了以下想法:

So I came up with the following idea:

template <typename T> struct vector : public std::vector<T>
{
    typedef std::vector<T> base;

    int size() const     { return base::size(); }
    int max_size() const { return base::max_size(); }
    int capacity() const { return base::capacity(); }

    vector()                  : base() {}
    vector(int n)             : base(n) {}
    vector(int n, const T& t) : base(n, t) {}
    vector(const base& other) : base(other) {}
};

template <typename Key, typename Data> struct map : public std::map<Key, Data>
{
    typedef std::map<Key, Data> base;
    typedef typename base::key_compare key_compare;

    int size() const     { return base::size(); }
    int max_size() const { return base::max_size(); }

    int erase(const Key& k) { return base::erase(k); }
    int count(const Key& k) { return base::count(k); }

    map() : base() {}
    map(const key_compare& comp) : base(comp) {}
    template <class InputIterator> map(InputIterator f, InputIterator l) : base(f, l) {}
    template <class InputIterator> map(InputIterator f, InputIterator l, const key_compare& comp) : base(f, l, comp) {}
    map(const base& other) : base(other) {}
};

// TODO: similar code for other container types

基本上是STL类的方法返回size_type覆盖返回只是'int'。

What you see is basically the STL classes with the methods which return size_type overridden to return just 'int'. The constructors are needed because these aren't inherited.

你会认为这是一个开发人员,如果你看到一个像这样的解决方案现有的代码库?

你会认为'whaa,他们正在重新定义STL,什么是巨大的WTF!简单的解决方案,以防止错误和增加可读性。或者也许你宁愿看到我们花了(半)一天左右改变所有这些循环使用std :: vector<> :: iterator?

Would you think 'whaa, they're redefining the STL, what a huge WTF!', or would you think this is a nice simple solution to prevent bugs and increase readability. Or maybe you'd rather see we had spent (half) a day or so on changing all these loops to use std::vector<>::iterator?

特别是如果这个解决方案结合使用无符号类型除了原始数据(例如unsigned char)和位掩码之外。)

(In particular if this solution was combined with banning the use of unsigned types for anything but raw data (e.g. unsigned char) and bit masks.)

推荐答案

我做了这个社区wiki ...请编辑它。我不同意针对int的建议。我现在看到的不错。



是的,我同意Richard的看法。你不应该在这样的循环中使用'int'作为计数变量。下面是你可能想使用索引做各种循环(虽然没有什么理由,偶尔这可能是有用的)。

I made this community wiki... Please edit it. I don't agree with the advice against "int" anymore. I now see it as not bad.

Yes, i agree with Richard. You should never use 'int' as the counting variable in a loop like those. The following is how you might want to do various loops using indices (althought there is little reason to, occasionally this can be useful).

for(std::vector<int>::size_type i = 0; i < someVector.size(); i++) {
    /* ... */
}



向后



您可以这样做,这是完美定义behaivor:

Backward

You can do this, which is perfectly defined behaivor:

for(std::vector<int>::size_type i = someVector.size() - 1; 
    i != (std::vector<int>::size_type) -1; i--) {
    /* ... */
}

很快,使用c ++ 1x(下一个C ++版本) ,你可以这样做:

Soon, with c++1x (next C++ version) coming along nicely, you can do it like this:

for(auto i = someVector.size() - 1; i != (decltype(i)) -1; i--) {
    /* ... */
}

递减低于0会导致我回绕,因为它是无符号的。

Decrementing below 0 will cause i to wrap around, because it is unsigned.

这不应该是一个参数,使用'int')。

That should never be an argument to make it the wrong way (using 'int').

C ++标准在 23.1 p5容器需求 T :: size_type ,用于 T c $ c> Container ,这种类型是一些实现定义的无符号整数类型。现在,使用 std :: size_t 为上面的 i 可以让bug静静地啜泣。如果 T :: size_type 小于或大于 std :: size_t ,那么它将溢出 i ,甚至不到(std :: size_t)-1 if someVector.size = 0 。同样,循环的条件将完全中断。

The C++ Standard defines in 23.1 p5 Container Requirements, that T::size_type , for T being some Container, that this type is some implementation defined unsigned integral type. Now, using std::size_t for i above will let bugs slurp in silently. If T::size_type is less or greater than std::size_t, then it will overflow i, or not even get up to (std::size_t)-1 if someVector.size() == 0. Likewise, the condition of the loop would have been broken completely.

这篇关于对于大多数签名/未签名警告,可接受修复?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆