std::vector::size()返回一个size_type无符号的,通常是相同的size_t,例如64位平台上的8个字节.
相比之下,即使在64位平台上也会QVector::size()返回一个int通常为4个字节的数据,并且它会被签名,这意味着它只能在2 ^ 32的一半时间内返回.
这是为什么?这似乎非常不合逻辑并且在技术上也有限制,虽然你很可能不需要超过2 ^ 32个元素,但是使用signed int会减少一半,这是没有明显的理由.也许是为了避免编译器警告让人们懒得声明i为一个uint而不是一个int谁决定让所有容器返回一个没有意义的大小类型是一个更好的解决方案?原因可能不是那么愚蠢?
lpa*_*app 18
至少从Qt 3开始已经多次讨论过这个问题,并且QtCore维护者表示,如果有的话,不久之前就不会发生任何变化,直到Qt 7.
当时正在进行讨论时,我认为有人会迟早在Stack Overflow上提起它......也可能在其他几个论坛和Q/A上.让我们试着揭开局面的神秘面纱.
一般来说,你需要明白这里没有更好或更糟,因为QVector它不是替代品std::vector.后者不会进行任何写入时复制(COW),而且需要付出代价.它基本上是针对不同的用例.它主要用于Qt应用程序和框架本身,最初用于QWidgets.
size_t 也有自己的问题,毕竟我将在下面说明.
如果没有我向你解释维护者,我会直接引用Thiago来传达官方立场的信息:
有两个原因:
1)它已签名,因为我们在API中的几个位置需要负值:indexOf()返回-1表示未找到的值; 许多"from"参数可以采用负值来表示从最后开始计数.所以,即使我们使用64位整数,我们也需要它的签名版本.这是POSIX ssize_t或Qt qintptr.
当您将unsigneds隐式转换为signed时,这也避免了符号更改警告:
-1 + size_t_variable => warning
size_t_variable - 1 => no warning
Run Code Online (Sandbox Code Playgroud)
2)它只是"int"以避免转换警告或与使用大于int的整数相关的丑陋代码.
size_t maxPathName = ::pathconf(nativePath.constData(), _PC_NAME_MAX);
if (maxPathName == size_t(-1))
Run Code Online (Sandbox Code Playgroud)
if (len < 0 || len != qint64(size_t(len))) {
Run Code Online (Sandbox Code Playgroud)
qint64 QIODevice::bytesToWrite() const
{
return qint64(0);
}
return readSoFar ? readSoFar : qint64(-1);
Run Code Online (Sandbox Code Playgroud)
那是来自蒂亚戈的一封电子邮件,然后还有另一个可以找到详细答案的地方:
即使在今天,核心内存超过4 GB(甚至2 GB)的软件也是例外,而不是规则.查看某些过程工具的内存大小时请小心,因为它们不代表实际的内存使用情况.
无论如何,我们在这里谈论的是有一个容器可以处理超过2 GB的内存.由于Qt容器的隐式共享和写时复制性质,这可能是非常低效的.编写此类代码时需要非常小心,以避免触发COW,从而使内存使用量增加一倍或更差.此外,Qt容器不处理OOM情况,因此如果您在任何接近内存限制的地方,Qt容器是错误的工具.
我在我的系统上拥有的最大进程是qtcreator,它也是唯一一个在VSZ(4791 MB)中穿过4 GB标记的进程.您可能会认为这表明需要64位容器,但您错了:
Qt Creator没有任何需要64位大小的容器,它只需要64位指针
它没有使用4 GB的内存.那只是VSZ(映射内存).Creator当前可访问的总RAM仅为348.7 MB.
它使用超过4 GB的虚拟空间,因为它是一个64位应用程序.因果关系与你期望的相反.作为证明,我检查了填充消耗了多少虚拟空间:800 MB.32位应用程序永远不会这样做,这是4 GB上可寻址空间的19.5%.
(填充是分配的虚拟空间,但没有任何东西支持;它只是存在,所以其他东西不会映射到那些页面)
通过Thiago的回答进一步讨论这个话题,请看:
就个人而言,我很高兴Qt集合大小签名.对我来说,使用减法表达式中可能使用的整数值是无符号的(例如size_t)似乎很难 .
无符号整数不保证涉及该整数的表达式永远不会为负数.它只能保证结果绝对是灾难.
另一方面,C和C++标准定义了无符号溢出和下溢的行为.
有符号整数不会溢出或下溢.我的意思是,他们这样做是因为类型和CPU寄存器的位数有限,但标准说他们没有.这意味着编译器将始终优化,假设您不会使它们上溢或下溢.
例:
for (int i = 1; i >= 1; ++i)
Run Code Online (Sandbox Code Playgroud)
这被优化为无限循环,因为有符号整数不会溢出.如果将其更改为unsigned,则编译器会知道它可能会溢出并返回到零.
有些人不喜欢这样:http://gcc.gnu.org/bugzilla/show_bug.cgi?id = 30475