【问题标题】:Is it possible to initialize a new allocated block to 0?是否可以将新分配的块初始化为 0?
【发布时间】:2015-07-15 12:42:58
【问题描述】:

我已经阅读了一些方法,例如为已知数量的值执行此操作,例如:

new int[3] {0 , 0, 0};

这让我想起了C 中声明时初始化数组的方式 我问自己在C++ 中也可以这样做:

new int[n] {}

空括号导致所有内容都被0-initialized。 尝试后对我来说看起来不错,但也可能是由随机性和真实 UB 或其他原因引起的。

如果它是有效的,还有没有办法在一个特定的值上初始化?

注意:

我想实现与调用calloc (n, sizeof(int)); 相同的效果。但是因为我现在在C++ 而不是C,所以我不会再使用这些函数来保持代码的可读性。

注2:

说的时候

我想实现[...]

它对应于我的最小示例,我只是想获得一个零初始化的有效内存块。

【问题讨论】:

  • 为什么不使用std::arraystd::vector
  • nconst 类型的吗?
  • @Slava 因为这是一个最小的例子,我只需要一个零初始化内存块,而不是任何向量或数组实现......
  • @awesomeyi:不,每次输入new 的范围时都会有所不同。
  • 必须...不要...说... calloc。

标签: c++ new-operator


【解决方案1】:
auto array = new int[n] ();

这执行零初始化,因为int 是“非类类型”。

auto array = new int[n];

这不是。初始值是不确定的。请注意,尽管这背后的背景非常混乱,并且标准中的描述更改了几次,可能是为了减少混乱,但恕我直言,未能达到其效果。因此,一些相关链接:

(也请阅读 cmets)

[...] 我只需要一个零初始化内存块,而不是任何向量或数组实现...

std::vector 一个简单的内存块。用它。除非您使用它们,否则它提供的其他成员函数是免费的。如果您不需要它,将不会调整大小。使用它的原因与您应该尽可能首选 std::unique_ptrstd::shared_ptr 而不是原始指针的原因相同!

【讨论】:

    【解决方案2】:

    我不会使用 new operator 并使用 C++ STL 容器,例如 std::vectorstd::array。这是一个小例子,因为您在编译时知道大小:

    std::array<int,3> foo{}; // will initialize a std::array with 0 value.
    

    关于初始化的更多解释:

    new int[5] ()zero initialization 有效且将元素初始化为0。

    2) 作为非类类型的值初始化序列的一部分,对于 没有构造函数的值初始化类类型的成员。

    new int[5]default initialization 你不能保证,因为这些值是任意填充的。

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

    【讨论】:

    • 这让我很困惑。到目前为止,我在标准中读到new() 之间的区别在于,使用它们它是默认初始化的,而没有它则不是。但我无法弄清楚“默认初始化”是什么意思。甚至在它自己的标准文档中也没有(当然在他们的但我找不到)
    • 嗯,我会根据这个修改我的答案:en.cppreference.com/w/cpp/language/default_initialization
    • 我愿意。 OP要求一个最小的例子,并表示他打算让事情变得简单;但是,您回复的代码需要大量困难且重复的错误处理才能安全使用。
    • 感谢您的评论。事实上,我一直专注于两种实现之间的解释。我没有看到 OP 想要“做这件事的好习惯”。因此,我添加了我的建议。
    【解决方案3】:

    只写new int[n] 只是分配内存并且什么都不初始化,所以给定的字节仍然有来自过去另一个用途的值,这是未知的。

    通过添加括号,C++ 添加了一个构造并用零填充空字段。

    更多信息,请阅读this

    【讨论】:

    • 你提到的源代码真的是关于 c++ 的吗?对我来说,它看起来像普通的 C,因为它指的是 c99 和 VLA,这在 c++ 中甚至无效。
    • @Zaibis 好点。大多数 C99 特性都被 C++ 采用,包括简单的数组初始化形式。为了更清楚,我参考了相关的 C++ 文档default initializationdirect initialization。从 C++11 开始,甚至还有 list initialization 也可以用于 POD。
    【解决方案4】:

    您可以使用std::vector

    std::vector<int> x(5);
    

    这里的主要优点是std::vector 实际上是安全的,不像new

    【讨论】:

    • 安全是什么意思?
    • 我的意思是,如果你想以一种不会泄漏内存、双重删除内存、释放后使用内存、损坏堆等的方式使用new,这对任何人来说几乎是不可能的非平凡的程序,这样做需要一大堆非常复杂的异常安全和相关问题,这绝对不简单。 std::vector 的人已经为您实现了它,使您的程序更简单
    猜你喜欢
    • 1970-01-01
    • 2020-09-15
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 2021-09-21
    • 1970-01-01
    • 1970-01-01
    • 2013-06-17
    相关资源
    最近更新 更多