C++ 在堆上创建对象是否需要对象的大小?

C++ 在堆上创建对象是否需要对象的大小?,c++,heap,definition,forward-declaration,C++,Heap,Definition,Forward Declaration,当编译器需要知道C(类)的大小时 对象:例如,在分配 C在堆栈上或作为直接固定的 其他类型的成员 < C++ >编码标准:101条规则、准则和最佳实践 这是否意味着对于堆分配的对象,大小是不必要的 Class C;//just forward declaration C * objc = new C(); Class C;//just forward declaration C * objc = new C(); 不,此列表只是示例,而不是排除。显然,在堆分配中必须知道对象大小,以便分配正确

当编译器需要知道C(类)的大小时 对象:例如,在分配 C在堆栈上或作为直接固定的 其他类型的成员

< C++ >编码标准:101条规则、准则和最佳实践

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

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

不,此列表只是示例,而不是排除。显然,在堆分配中必须知道对象大小,以便分配正确的内存量。

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

对象大小由
new
操作符计算:

Object *o = new Object();

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

对象大小由
new
操作符计算:

Object *o = new Object();

您不需要明确地告诉<代码>新< /Cord>对象大小,但它确实计算它(使用<代码> sieOfs运算符),以便在堆上分配正确的空间量。

作为程序员,您几乎不需要知道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
}

作为程序员,你几乎不需要知道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
}

不可以。为了在堆上分配对象,您必须知道其大小

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

不可以。为了在堆上分配对象,您必须知道其大小

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

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

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

要回答您的特定问题:

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

Class C;//just forward declaration
C * objc = new C();
Class C;//just forward declaration
C * objc = new C();
C++不会让你这么做

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

  • 操作员
    new
    只能与完整类型一起使用。根据C++98标准5.3.4-“[分配的]类型应为完整的对象类型,但不是抽象类类型或其数组”

  • 编译器不知道存在什么构造函数(并且可以访问),因此它也将因此而失败


  • 要回答您的具体问题:

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

    Class C;//just forward declaration
    C * objc = new C();
    
    Class C;//just forward declaration
    C * objc = new C();
    
    C++不会让你这么做

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

  • 操作员
    new
    只能与完整类型一起使用。根据C++98标准5.3.4-“[分配的]类型应为完整的对象类型,但不是抽象类类型或其数组”

  • 编译器不知道存在什么构造函数(并且可以访问),因此它也将因此而失败


  • 问题是标记C++,而不是C。这在C++中是有效的。例如,我们在VS C++运行时的源代码中看到,新操作符通过内存调用MALLC,因此在分配时隐式地知道大小,甚至在这里,“程序员”不知道大小。它是一个知道它的编译器(你问它并把答案传递给malloc)Foo*Foo=(Foo*)malloc(sizeof(Foo));而且,仅仅因为一个编译器简单地包装了malloc,并不意味着另一个编译器就包装了malloc。另外,如果Foo有一个构造函数,你只是创建了一个Foo,而没有运行它。通常我假设,如果编译器代表我知道一些东西,这与我知道的东西基本上是一样的,即使我没有将该东西的值打印到屏幕上。例如,我们可能有任何本地变量来计算临时值——你不必查看调试器中的值来表示你“知道”那个值,它可能只够引用代码中的变量。问题是标记C++。这不是C。这在C++中是有效的。例如,我们在VS C++运行时的源代码中看到,新操作符通过内存分配到MALOC,所以在分配时隐式地知道了大小,甚至在这里,“程序员”不知道大小。它是一个知道它的编译器(你问它并把答案传递给malloc)Foo*Foo=(Foo*)malloc(sizeof(Foo));而且,仅仅因为一个编译器简单地包装了malloc,并不意味着另一个编译器就包装了malloc。另外,如果Foo有一个构造函数,那么您只是创建了一个Foo而没有运行它