size_t和内存分配

时间:2017-09-11 16:47:05

标签: c++ c++11 memory-management

有这样的类型std::size_t。它可以用于描述对象的大小,因为它可以保证能够表达任何对象的最大大小(因此写成here)。但是,这是什么意思?我们实际上没有内存中的对象。那么这是否意味着这种类型可以存储一个整数,表示我们理论上可以使用的最大内存量?

如果我尝试写类似

的内容
size_t maxSize = std::numeric_limits<std::size_t>::max();
new char[maxSize];

我会收到错误,因为数组的总大小限制为0x7fffffff。为什么? 此外,如果我传递一个等于maxSize的非常量表达式,则会抛出std::bad_array_new_length。如果我传递的表达式小于maxSize但仍然大于0x7fffffff,则会抛出std::bad_alloc。我想由于缺少内存而抛出std::bad_alloc,而不是因为大小大于0x7fffffff。为什么会这样?我想如果要分配的内存大小大于0x7fffffff(这是传递给const的const的最大值),抛出 特殊 异常是很自然的。 new []在编译时)。为什么std::bad_array_new_length只有在我通过maxSize时才被抛出?这种情况特别吗?

顺便说一下,如果我将maxSize传递给vector的构造函数,如下所示:

vector<char> vec(maxSize);

std::bad_alloc将被抛出,而不是std::bad_array_new_length。这是否意味着vector使用不同的分配器?

我正在尝试自己创建数组。使用unsigned int来存储大小,容量和索引是一种糟糕的方法。因此,定义一些这样的别名是个好主意:

typedef std::size_t size_type;

并使用size_type代替unsigned int

1 个答案:

答案 0 :(得分:3)

答案是在创建动态存储持续时间对象的过程中。

简而言之,当程序执行新表达式时:new char[size]

  1. 它检查s=size*sizeof(char)+x是否有效大小(实现定义为0x7fffffff,这取决于ABI)(如果您创建一个简单可破坏类型的数组,则在大多数平台上x = 0)。如果大小无效,则会抛出bad_array_new_lenght,否则会抛出

  2. 它调用分配函数::operator new(s)。这个函数的第一个参数是std::size_t,这就是为什么std::size_t必须足够大才能创建任何大小的对象(数组是一个对象)。

  3. 此分配函数要求系统保留大小为s的存储区域。如果系统成功保留此空间,则返回指向存储区域开头的指针。否则它会调用新处理程序并重试分配,但如果它再次失败,则会抛出bad_alloc

  4. 如果分配成功,默认初始化(在这种情况下)分配的存储上的size char(无操作),它也可能将数组的大小存储在此分配的存储上(原因是添加x)(这是在执行删除表达式时使用的,以便知道必须调用许多析构函数如果析构函数是微不足道的,那么这不是必需的。)

  5. 您将在c ++标准中找到所有细节(§6.7.4[basic.stc.dynamic],§8.3[expr.new],§8.4[expr.delete],§21.6[support.dynamic])

    对于最后一个问题,您可以考虑使用签名类型作为索引和对象大小。即使对象大小或索引不应该是负数,标准规定无符号算术遵循模运算,这严格限制了优化。此外,无符号整数类型的算术和比较是错误的常见主题。由于兼容性原因,std::size_t是无符号的,因此选择是无符号的,因为史前机器很短! (16位或更少!)