Important: Please read the Qt Code of Conduct -

Negative container size?

  • Hello guys,

    I don't know if this is supposed to be reported as a bug. But does it ever make sense to have the return the size of QVector, QStringList and many other containers as a signed integer? this is really stupid!!!! I always have to cast my counters' variables to fit these functions!!!

    Any ideas?

  • Hi,

    I'm so used to just using integes when doing this like declaring for loops that I guess being signed is better for me, though since you can't have a negative number of items in a container, I guess it would make sense if it were unsigned.

    However, I'd have to start casting my code then! ;OP

  • Thanks for the reply.

    The problem is that it contradicts with the C++ standard. If you check the Std containers (vectors, deques, lists, etc..., you'll find that they all return unsigned long integers for size()...

    I really need someone to give me a good reason for doing this...!!! it's very unnatural!!

  • Moderators

    The really good thing about the use of unsigned is that it is harder to get integer overflows.

    for (int i = list.count(); i >= 0; --i) {
    do(something, on, list);

    does not terminate when using an unsigned int for i, while it is no problem when using int. I don't know about you, but I did fall into that trap before when using the STL.

    Then there are some handy (but not necessarily obvious) things possible due to using int:

    In some places negative ints are used to signal error conditions:
    int pos = list.indexOf(someitem);
    if (pos < 0)
    // not found

    Since the position is limited to int the size is also limited to int. This enables you to do:
    QList<int> partlist = origList.mid(5, -1 /* to the end of string, actually this is the default, so I could have left the -1 out :-) */);

    With strings negative numbers are also used to right align text in some places, e.g. when using arg to insert numbers into strings:
    leftAligned = QString::fromLatin1("some text %1").arg(15, 8 /* field width, right aligned /);
    rightAlingned = QString::fromLatin1("some other text %1").arg(15, -8 /
    field width, left aligned */);

  • Thank you for your reply.

    Yes it makes sense for the mid function and for some other error checks. I agree. But still, size() doesn't have to return a negative value under any circumstances. You're killing half of the capacity there with no real use!!!! is there a single use of having the return value of specifically the method size() signed?

  • Moderators

    As Tobias mentioned, since some of the methods which operate on the list (indexOf(), for instance) use signed integers to return their value (using negative numbers for "None"), then it must limit the capacity to that which can be accessed by a signed integer. If you could have an unsigned int's worth of capacity, then it would be practically useless to only be able to address half of that space with those operators which have to return a signed int.

  • Using signed 32 bit integers, you have 2^31 = 2,147,483,648. That is more than two billion objects in the container. If you run onto the limits in your use case, the standard Qt containers might not be appropriate at all. Not to mention some memory problems. If each of the objects takes only 10 bytes to store, it will still take up more than 20 GB. That will be much more of a problem than an integer overrun.

  • The only two containers I can think of that might still be manageble and useful with the full integer range, are QByteArray and QBitArray. For all other cases Volker is right: you're out of memory before you're out of ints :-)

    And you cannot use the full integer range only for things like size. That would imply that you expect to be able to actually store that number of items in your container, which would imply that the rest of API would have to conform. Or do you think it would be acceptable to have some parts of the API only work as long as the size is smaller than 2^31 bytes, while others will always work?

  • I don't know... You guys have a point. But it's only that I'm very used to the standard C++ form, which makes stuff always bad when I gotta convert between containers. I automatically write "unsigned long int" when I deal with loops that have to deal with containers; and I have some classes that have nothing to do with Qt, and some others with QObject that use Qt containers. When I transfer data between them I always fall into the problem of either having warnings in my compilation process, or statically casting my data, which I find unnecessary and annoying up to some level. It just doesn't comply with the standard every standard C++ programmer knows. :-)

Log in to reply