【问题标题】:Does `new` allocate enough memory for any instance?`new` 是否为任何实例分配了足够的内存?
【发布时间】:2022-01-06 16:35:32
【问题描述】:

如果我用

创建Foo
Foo* foo = new Foo();

然后重新分配foo

Foo mkfoo();

*foo = mkfoo();

我可以确定我已经为mkfoo 创建的这个新实例分配了足够的内存吗?即使Foo 具有动态大小的内容,例如std::vector 使用 mkfoo() 创建时的内容与使用 new Foo() 创建时的内容不同?如果不是,那么分配内存的最佳方式是什么?

【问题讨论】:

  • Foo 类型的每个对象都具有完全相同的大小。这适用于所有类型。任何需要动态内存量的东西都需要使用动态内存分配,它存储在对象本身之外。
  • Foo 类型的每个对象都具有相同的大小。 std::vector<whatever> 类型的每个对象都具有相同的大小。从向量中添加和删除元素不会改变它的大小;它改变了它管理的动态内存。
  • 但是,这并不一定意味着您可以提前知道您将有足够的内存来完成作业。如果无法分配足够的内存,std::vector 复制构造函数可能会抛出。如果您想为如何使用内存提供自己的保证,则必须考虑为向量使用自定义分配器。
  • 请注意,当您重新分配 foo 时,foo 指向的初始堆内存仍然存在。此外,指向向量的指针通常是一种代码味道。
  • @doug 确实如此。我能做的事情非常有限,因为我在一个只能返回指针的 FFI 世界中工作

标签: c++ memory memory-management new-operator


【解决方案1】:

是的。 “完整类型”的部分定义是它的大小是已知的。

对于包含动态大小成员(如std::vector)的类型,这些成员的动态存储也在堆上分配,因此在考虑sizeof 对象时,该存储的大小不是计算的一部分。

【讨论】:

    【解决方案2】:

    线

    *foo = mkfoo();
    

    不会在从new 返回的存储中创建新的Foo 对象。它只是在已经存在的Foo 对象上调用赋值运算符重载。

    即使你使用例如一个placement-new 在原始new 表达式返回的存储中实际创建一个新的Foo 对象,这很好,因为相同类型的对象总是具有相同的对象大小(sizeof)确定存储大小他们占据了。

    如果你有std::vector<int>这样的容器,它自己的对象大小(sizeof)也总是一样的。但是它将包含例如指向存储向量元素的其他内存的指针(具体如何完成是实现细节)。如果您在std::vector 上调用.size(),则不会获得std::vector 对象的大小,而是向量存储的元素数量,但这些元素并未存储在std::vector 对象本身的内存中,等等不计入其对象大小。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 2011-01-06
      • 2019-11-18
      • 2014-04-24
      • 1970-01-01
      相关资源
      最近更新 更多