【问题标题】:Is the size of an object needed for creating object on heap?在堆上创建对象需要对象的大小吗?
【发布时间】:2010-10-31 06:57:15
【问题描述】:

当编译器需要知道一个 C(类)的大小时 对象:例如,当分配一个 C 在堆栈上或作为直接持有 另一种类型的成员

来自C++ 编码标准:101 条规则、指南和最佳实践

这是否意味着对于堆分配的对象,大小不是必需的?

Class C;//just forward declaration
C * objc = new C();

【问题讨论】:

  • 你问的是C++还是C?请编辑您的问题以澄清这一点。
  • 引文中的“你”是谁?作为程序员,你几乎不需要知道它。编译器有。我认为引用缺少上下文,以至于无法回答您的问题。
  • 基于标签(声明,定义),这句话试图解释为什么有时需要定义类型,而不仅仅是声明。因此,您很可能是编译器。
  • 道歉延迟回复现在可以了吗?
  • 前向声明用于没有分配的头文件中。在执行分配之前,您必须包含类的完整定义,无论它是在堆上还是在堆栈上。

标签: c++ heap-memory definition forward-declaration


【解决方案1】:

不,此列表仅作为示例而非排除。显然,在堆分配中必须知道对象的大小,这样才能分配正确的内存量。

【讨论】:

    【解决方案2】:

    回答您的具体问题:

    这是否意味着堆分配 对象大小不是必须的吗?

    Class C;//just forward declaration
    C * objc = new C();
    

    C++ 不会让你这样做。

    即使它可以让您通过稍后神奇地解析大小来对不完整的类型执行“new”(我可以设想在链接器的合作下这在技术上是可能的),但尝试在编译时会失败时间至少有两个原因:

    1. 运算符new 只能用于完整类型。从 C++98 标准 5.3.4 - “[分配的] 类型应该是完整的对象类型,但不是抽象类类型或其数组”

    2. 编译器不知道存在哪些构造函数(并且可以访问),因此它也将因此失败。

    【讨论】:

      【解决方案3】:

      对象大小由new 运算符计算:

      Object *o = new Object();
      

      您不需要明确告诉new 对象大小,但它会计算它(使用sizeof 运算符)以便在堆上分配正确的空间量。

      【讨论】:

      • 我相信这个问题更精确一些,因为它似乎询问该类型的前向声明是否足以在堆中创建一个对象。 sizeof() 是编译器通过类型和大小的知识计算出来的,你不需要知道它,但编译器知道。
      【解决方案4】:

      作为程序员,您几乎不需要知道 C++ 中对象的大小。例如:

      class A {
          ...  // member data
      };
      
      void f() {
          A a;              // allocate on stack
          A * p = new A;    // allocate on heap
      }
      

      在这两种情况下,程序员都不需要知道大小 - 编译器当然需要知道它。

      请注意,无论您如何创建一个对象,编译器在创建时都必须知道它的大小:

      class B;     // forward declaration - no size:
      
      void f() {
          B b;              // compilation error
          B * p = new B;    // compilation error
      }
      

      【讨论】:

      • 隐式地,这两种情况下的大小都是已知的。只是不一定由你来 - 但如果编译器没有足够的知识来解决它,它会给出一个错误
      【解决方案5】:

      没有。为了在堆上分配一个对象,你必须知道它的大小。

      Foo *foo=(Foo *)malloc(sizeof(*foo));
      

      【讨论】:

      • 问题标记为 C++,而不是 C。
      • 这在 C++ 中有效——例如,我们在 VS C++ 运行时的源代码中看到 new 运算符调用 malloc 进行内存分配,因此在分配时隐式知道大小
      • 即使在这里“你”作为一个程序员也不知道大小。它是一个知道它的编译器(你问它并将答案传递给 malloc)
      • Foo *foo=(Foo *)malloc(sizeof(Foo));此外,仅仅因为一个编译器简单地包装了 malloc,并不意味着另一个编译器这样做。另外,如果 Foo 有一个构造函数,你只是创建了一个 Foo 而不运行它。
      • 通常我假设如果编译器代表我知道某件事,这本质上就好像我知道它一样,即使我实际上并没有将那件事的值打印到屏幕上.例如,我们可能有任意数量的局部变量来计算临时值 - 您不必在调试器中查看该值即可说您“知道”该值,仅引用该变量可能就足够了在您的代码中。
      【解决方案6】:

      编译器必须看到类的声明有两个原因:它必须知道它必须分配的大小(正如其他人已经指出的那样),还因为编译器必须知道如何构造对象:它是否具有默认值构造函数,隐式定义的默认构造函数,没有默认构造函数?即使可以使用无参数构造函数创建对象,编译器也必须知道。

      【讨论】:

        猜你喜欢
        • 2016-10-23
        • 1970-01-01
        • 2015-03-12
        • 1970-01-01
        • 2016-07-04
        • 1970-01-01
        • 2013-09-26
        • 1970-01-01
        • 2010-12-08
        相关资源
        最近更新 更多