【问题标题】:Allocated array already zeroed分配的数组已经归零
【发布时间】:2012-11-27 21:13:26
【问题描述】:

在 C++11 中,当我使用 T *array = new T[n]; 分配动态数组时,它已经归零(使用 gcc 4.7.2,Ubuntu 12.10 64 位)。

  1. 这是 C++11 规范强制要求的吗?
  2. 如何在不将其项归零的情况下分配数组?这应该会快一点。

编辑:我已经检查了T = int

gcc cxx-flags-std=gnu++11 -O3 -ffast-math -fno-rtti

【问题讨论】:

  • 可能是编译器标志?在 Visual Studio 中,这将在调试版本中发生,但不会在发布中发生
  • @emartel 好吧,我检查过了,我在发布模式下构建。我会在问题中添加标记。
  • T是什么类型的?将为每个 T 触发默认构造函数;如果该构造函数只是“将其归零”,那么您会看到这一点。如果 T 是 POD,则不能保证使用 new 进行零初始化。
  • 不保证零初始化。见this recent related question

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


【解决方案1】:

§ 5.3.4

如果省略了new-initializer,则对象是默认初始化的(8.5);如果不执行初始化, 该对象具有不确定的值。

new-initializer 是new T[] () 中的(),你已经省略了。

§ 8.5 / 6

默认初始化 T 类型的对象意味着:

——如果 T 是一个(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(并且 如果 T 没有可访问的默认构造函数,则初始化是非良构的);

——如果 T 是一个数组类型,每个元素都是默认初始化的;

——否则,不执行初始化。

int[] 是默认初始化的 -> 每个元素都是默认初始化的。

“这是由 C++11 规范强制执行的吗?”:“不执行初始化”,所以不,如果 T 没有归零构造函数(即 T 是 POD),则不会强制归零。对于 T=int,不必执行归零。

为什么它还是零?如果您的程序从操作系统分配新内存,操作系统会为您清零新内存。如果您可以读取另一个可能存储敏感数据的程序的内存,那将是非常危险的。但是,如果您写入该内存,释放它并再次分配其中的一些,它不应该被归零。

【讨论】:

    【解决方案2】:

    它不会被初始化(当然,如果 T 是一个类,仍然会调用构造函数)。要强制值初始化(这个名称对新手来说可能会产生误导 - 我们称之为零初始化,它适用于像 int 这样的原始类型),请执行

    new T[N]()
    

    也就是放一对括号。

    【讨论】:

      【解决方案3】:

      取决于您的实际类型T。在某些条件下,它可能会被初始化为零。见这里:Default initialization in C++

      【讨论】:

      • 我已经检查了T = int
      【解决方案4】:

      即使您可以使用 C++ 功能来动态分配未初始化的内存 (std::get_temporary_buffer?),您操作系统的 libc 中 malloc()::new 的底层实现是使用匿名 mmap() 来表示 large 分配块(其中 large 是一个可调参数)。并且匿名mmap() 总是零初始化。

      【讨论】:

        猜你喜欢
        • 2018-09-01
        • 2020-02-11
        • 2017-09-26
        • 2015-09-04
        • 2012-01-28
        • 2012-01-27
        • 2014-07-01
        • 2018-12-19
        • 2011-12-26
        相关资源
        最近更新 更多