【问题标题】:What happens to class members when malloc is used instead of new?当使用 malloc 而不是 new 时,类成员会发生什么?
【发布时间】:2010-05-26 15:11:16
【问题描述】:

我正在准备期末考试,我偶然发现了一个奇怪的问题,这是我们的老师去年为一些可怜的人提供的考试的一部分。问题是这样的:

以下程序是否正确?如果是,请写下程序输出的内容。如果不是,请写下原因。

程序:

#include<iostream.h>
class cls
{     int x;
      public: cls() { x=23; }
      int get_x(){ return x; } };
int main()
{     cls *p1, *p2;
      p1=new cls;
      p2=(cls*)malloc(sizeof(cls));
      int x=p1->get_x()+p2->get_x();
      cout<<x;
      return 0;
}

我的第一反应是“程序不正确,因为应该使用new 而不是malloc”。但是,在编译程序并看到它输出 23 后,我意识到这个答案可能不正确。

问题是我期待p2-&gt;get_x() 返回一些任意数字(当调用malloc 时,内存的那个位置发生了什么)。但是,它返回 0。我不确定这是否是巧合,或者当它是 malloc-ed 时,类成员是否被初始化为 0。

  • 这是默认行为(p2-&gt;xmalloc 之后为 0)吗?我应该预料到会这样吗?
  • 你的会回答我老师的问题吗? (除了忘记#include &lt;stdlib.h&gt;malloc :P)

【问题讨论】:

  • 为什么 0 也不能是任意数字?
  • 除此之外&lt;iostream.h&gt; 应该只是&lt;iostream&gt;
  • 您还可以修复老师的内存泄漏问题。
  • FMI UNIBUC 的斗争

标签: c++ memory-management malloc


【解决方案1】:
  • 这是默认行为(p2->x 在 malloc 之后为 0)吗?我应该预料到这一点吗?

不,p2->x 可以是调用 malloc 之后的任何内容。它恰好在您的测试环境中为 0。

  • 您对我老师的问题的回答是什么? (除了忘记#include for malloc :P)

每个人都告诉过你,new 结合了从 freestore 获取内存的调用和对对象构造函数的调用。 Malloc 只做了一半。

修复它:示例程序错误。在类中使用“malloc”并不总是错误的。它在共享内存的情况下是完全有效的,你只需要添加一个就地调用 new:

p2=(cls*)malloc(sizeof(cls));
new(p2) cls;

【讨论】:

  • 如果您使用placement new,您还必须显式调用析构函数(您不能使用delete,因为您没有使用new)。此外,您应该强调这并不常见(当您为多个项目(不仅仅是一个)预分配存储空间时构建自己的容器对象时使用 mainley)
  • 我主张使用reinterpret_cast。它强调你正在做一些非常危险的事情。
  • 回应 Matthieu M.,我不喜欢编辑 5 年前的问题,但 IMrecentE,我会将上面的最后一个示例重写为 void* p2Buffer=malloc(sizeof(cls)); cls* p2 = new(p2Buffer) cls;.这样你以后可以调用 p2->~cls 和 free(p2Buffer);很明显p2是“类对象”,p2Buffer是分配的内存指针。
【解决方案2】:

new 调用构造函数,malloc 不会。所以你的对象将处于未知状态。

【讨论】:

  • 我知道malloc 不会调用构造函数。我的问题是关于班级成员x——它是用 0 初始化的,还是在那个位置获得一些内存中的随机值?
  • @Felix:如果不调用构造函数,则成员数据的值是未定义的行为。
  • @Felix 初始化 x 发生在构造函数中,所以它是未定义的。即使使用 new 也不会将 x 归零,除非 x 在构造函数中实际设置为 0;成员字段不会像在 Java 中那样获得默认初始化
  • 如果您在调试模式下构建,我相信内存可能会为 0。如果您处于释放模式,您可能会在该空间中看到一些随机数。
  • @tloach - 这取决于编译器。 Microsoft C++ 将在调试模式下用 0xcdcdcdcd (或类似的东西。释放的内存也填充一些类似的数字)填充未初始化的内存。在释放模式下,它在 malloc/new 期间根本不会修改内存。
【解决方案3】:

实际行为未知,因为new 的行为与malloc + constructor 调用非常相似。

在您的代码中,缺少第二部分,因此,它可以在一种情况下工作,但不能,但您不能准确地说。

【讨论】:

    【解决方案4】:

    为什么 0 也不能是任意数字?你在调试模式下运行吗?什么编译器?

    VC++ 用一串 0xCC 字节值(当然在调试模式下)预先填充新分配的内存,所以如果你使用它,你就不会得到零作为答案。

    【讨论】:

      【解决方案5】:

      Malloc 不保证将其分配的内存归零,并且程序的结果是未定义的。

      否则,还有许多其他因素使该程序无法成为正确的 C++。 cout 在命名空间std 中,malloc 需要通过#include &lt;cstdlib&gt; 包含在内,并且 iostream.h 也不符合标准。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-10-22
        • 2014-05-03
        • 2011-03-22
        • 1970-01-01
        相关资源
        最近更新 更多