为什么QVector :: size返回int?

时间:2014-10-28 22:47:36

标签: c++ qt size qtcore qvector

std::vector::size()会返回size_type,该size_t是无符号的,通常与QVector::size()相同,例如它在64位平台上是8个字节。

相反,int返回一个i,即使在64位平台上也通常是4个字节,并且在那时它被签名,这意味着它只能到达2 ^ 32的一半。

为什么?这似乎非常不合逻辑并且在技术上也有限制,虽然你很可能不需要超过2 ^ 32个元素,但是使用signed int会减少一半,因为没有明显的理由。也许是为了避免编译器警告,因为懒得将uint声明为int而不是{{1}}谁决定让所有容器返回一个没有意义的大小类型是一个更好的解决方案?原因可能不是那么愚蠢?

2 个答案:

答案 0 :(得分:17)

至少从Qt 3开始已经多次讨论这个问题了,QtCore维护者表示,如果它发生的话,不久之前就不会发生任何变化。

当讨论正在进行时,我认为有人会迟早在Stack Overflow上提起它......也可能在其他几个论坛和Q / A上。让我们试着揭开局面的神秘面纱。

一般情况下,您需要了解这里没有更好或更差,因为QVector 不是替代std::vector。后者不会进行任何写入时复制(COW),而且需要付出代价。它基本上是针对不同的用例。它主要用于Qt应用程序和框架本身,最初用于QWidgets。

size_t也有自己的问题,毕竟我将在下面说明。

如果没有我向你解释维护者,我会直接引用Thiago来传递official stance的消息:

  

有两个原因:

     

1)它已签名,因为我们在API中的几个地方需要负值:   indexOf()返回-1表示未找到的值;很多"来自"   参数可以取负值以指示从末尾开始计数。甚至   如果我们使用64位整数,我们需要它的签名版本。那就是   POSIX ssize_t或Qt qintptr。

     

当您将unsigneds隐式转换为时,这也可以避免出现符号更改警告   签名:

-1 + size_t_variable        => warning
size_t_variable - 1     => no warning
  

2)它只是" int"避免转换警告或与之相关的丑陋代码   使用大于int的整数。

IO / qfilesystemiterator_unix.cpp

size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX);
if (maxPathName == size_t(-1))

IO / qfsfileengine.cpp

if (len < 0 || len != qint64(size_t(len))) {

IO / qiodevice.cpp

qint64 QIODevice::bytesToWrite() const
{
    return qint64(0);
}

return readSoFar ? readSoFar : qint64(-1);

这是来自Thiago的一封电子邮件,然后是there is another,您可以在那里找到一些详细的答案:

  

即使在今天,核心内存超过4 GB(甚至2 GB)的软件也是如此   是一个例外,而不是规则。看着时要小心   某些流程工具的内存大小,因为它们不代表实际内存   的使用。

     

无论如何,我们在这里谈论有一个单一容器寻址   超过2 GB的内存。由于隐含共享&amp;写入时复制   Qt容器的性质,可能效率很低。你需要   在编写这样的代码时要非常小心,以避免触发COW   使你的记忆力增加一倍或更差。此外,Qt容器不处理OOM   情况,所以如果你在任何接近你的内存限制,Qt容器   是错误的工具。

     

我系统中最大的进程是qtcreator,它也是唯一的进程   一个跨越VSZ中的4 GB标记(4791 MB)。你可以说它是一个   表明需要64位容器,但你错了:

     
      
  • Qt Creator没有任何需要64位大小的容器,简单来说就是这样   需要64位指针

  •   
  • 它没有使用4 GB的内存。那只是VSZ(映射内存)。总数   目前创建者可访问的RAM仅为348.7 MB。

  •   
  • 它使用超过4 GB的虚拟空间因为它是64位   应用。因果关系与你的相反   期望。作为证明,我检查了消耗了多少虚拟空间   填充:800 MB。 32位应用程序永远不会那样做,19.5%的应用程序   4 GB上的可寻址空间。

  •   
     

(填充是分配的虚拟空间,但没有任何东西支持;它只是   那里有其他东西没有映射到那些页面)

使用蒂亚戈的回复进一步讨论这个话题,请看:

  
    
      

就个人而言,我非常高兴Qt集合大小已签名。它似乎       对我来说,一个整数值可能在表达式中使用       减法是无符号的(例如size_t)。

             

无符号整数并不保证表达式涉及       该整数永远不会是负数。它只保证结果       将是一场绝对的灾难。

    
  
     

另一方面,C和C ++标准定义了unsigned的行为   溢出和下溢。

     

有符号整数不会溢出或下溢。我的意思是,他们这样做是因为类型   和CPU寄存器的位数有限,但标准说它们   别&#39;吨。这意味着编译器将始终优化,假设您没有超过 -   或者下流他们。

     

示例:

for (int i = 1; i >= 1; ++i)
  

这被优化为无限循环,因为有符号整数不会溢出。   如果将其更改为unsigned,则编译器知道它可能会溢出   并回到零。

     

有些人不喜欢这样:http://gcc.gnu.org/bugzilla/show_bug.cgi?id=30475

答案 1 :(得分:2)

unsigned个数字是某些2^n的值n

有符号数是有界整数。

使用无符号值作为“正整数”的近似值会遇到这样的问题:公共值靠近域的边缘,其中无符号值的行为与普通整数不同。

优点是无符号逼近达到更高的正整数,并且在/溢出下定义得很好(如果看作是Z的模型则是随机的)。

但实际上,ptrdiff_t会优于int