【问题标题】:Does std::initializer_list heap allocate memory?std::initializer_list 堆是否分配内存?
【发布时间】:2020-09-01 15:37:01
【问题描述】:

简单的问题,std::initializer_list 堆是否分配内存?我不是在谈论它的元素项,只是用于存储元素的缓冲区本身。

【问题讨论】:

  • 我相信它的目的是在堆栈上临时分配(并且很可能也被优化掉)。不充当动态堆分配器。
  • 这是一个你不应该关心的实现细节,在不同的实现之间可能会有所不同,据我所知,标准并没有说明什么。

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


【解决方案1】:

这是一个有趣的问题。我同意 Josh 的回答,只是想补充一点,我创建了以下相关实验。我尝试编译并运行以下代码:

#include <iostream>
#include <vector>

int main()
{
   std::vector<int> v = {

#include "x.inc"

   };

   std::cout << v.size() << std::endl;
}

其中x.inc 包含 1 亿次 0, 加上结尾的 0,由该程序生成:

#include <fstream>

int main()
{
   std::ofstream f("x.inc");

   for (int i = 0; i < 100000000; i++)
      f << "0, ";
   f << "0\n";
}

使用 GCC 创建的可执行文件有 328 MB,这表明 std::intializer_list 的整个实例实际上是在程序的数据段中呈现的。运行时,没有分段错误,并且 Valgrind 报告没有堆分配,除了向量 v 所需的 400 MB。

【讨论】:

    【解决方案2】:

    这是cppreference 必须说的话(强调我的):

    在原始初始化列表对象的生命周期结束后,不能保证底层数组存在。 std::initializer_list 的存储是unspecified(即它可以是自动、临时或静态只读内存,具体取决于具体情况)。 (直到 C++14)

    底层数组是一个 const T[N] 类型的临时数组,其中每个元素都是从原始初始化列表的相应元素复制初始化的(除了缩小转换无效)。底层数组的生命周期与任何其他临时对象相同,只是从数组初始化一个 initializer_list 对象可以延长数组的生命周期,就像将引用绑定到临时对象一样(有相同的例外,例如初始化非-静态类成员)。底层数组可以分配在只读存储器中。 (C++14 起)

    说了这么多,可能不会。我想不出编译器或库作者会选择将其放在堆上的情况,但是“未指定”一词的使用听起来好像无法保证临时数组的分配方式。 C++ 标准中可能有更好的规范。

    另一个要点是您绝对不应该尝试编写底层数组内存。

    【讨论】:

      猜你喜欢
      • 2019-12-10
      • 2023-04-08
      • 2011-08-02
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 2017-02-15
      • 2021-11-06
      • 2015-09-11
      相关资源
      最近更新 更多