在C ++中,为什么需要new来动态创建对象而不是分配? [英] In C++, why is `new` needed to dynamically create an object rather just allocation?

查看:424
本文介绍了在C ++中,为什么需要new来动态创建对象而不是分配?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有这个简单的类层次结构:

I've got this trivial class hierarchy:

class Base {
public:
    virtual int x( ) const = 0;
};

class Derived : public Base {
    int _x;
public:
    Derived( int x ) : _x(x) { }
    int x( ) const { return _x; }
};

如果我使用malloc分配Derived的实例,然后尝试访问多态函数x,则程序崩溃(出现分段错误):

If I use malloc to allocate an instance of Derived, and then try to access the polymorphic function x, program crashes (I get a segmentation fault):

int main( ) {
    Derived *d;
    d = (Derived*) malloc( sizeof(Derived) );
    *d = Derived( 123 );

    std::cout << d->x() << std::endl; // crash

    return 0;
}

当然,我的实际应用程序要复杂得多(这是一种内存池).

Of course my actual application is a lot more complex (it's a sort of memory pool).

我很确定这是因为分配d的方式:我没有使用new.

I'm pretty sure it's because of the way I allocate d: I didn't use new.

我知道展示位置new 运算符,它一定是我需要的,但是我从未使用过它,并且遇到了一些问题:

I know of placement new operator, which must be what I need, but I've never used it and have got some questions:

  • 如果我不使用new,为什么我的应用程序崩溃?

  • why is my application crashing, if I don't use new?

new实际做什么?

为什么不能只使用赋值运算符将Derived( 123 );的值分配给d指向的存储区?

Why can't I just use the assignment operator to assign the value of Derived( 123 ); to the memory area pointed by d?

对于非多态类型,我还需要使用new吗?

Would I need to use new also for non-polymorphic types?

POD呢?

我链接了C ++ Faq 上方,它表示传递到位置new的内存区域必须与我正在创建的对象对齐.

On the C++Faq I linked above it says that the memory region passed to placement new must be aligned for the object I'm creating.

我知道什么是对齐方式,但是我不知道如何检查班级所需的对齐方式.

I know what alignment is, but I don't know how to check the alignment needed for my class.

malloc手册说:

malloc()和calloc()函数返回一个指向已分配内存的指针,该指针适合于任何类型的变量.

The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable.

我希望我班级需要的对齐方式是sizeof返回的班级大小,以便address_returned_by_malloc + i * sizeof(my_class)形式的任何地址都适合分配我的对象.

And I hope that the alignment needed for my class is the class size as returned by sizeof, so that any address in the form address_returned_by_malloc + i * sizeof(my_class) is suitable to allocate my objects.

我的希望对吗?

推荐答案

让我们走下去

  1. 如果我不使用new,为什么我的应用程序崩溃?

虚拟表已损坏.

虚拟表卡在分配的内存之后.当您new一个类时,生成的代码将正确设置vtable.但是,malloc无法正确初始化vtable

The virtual table is stuck right after the allocated memory. when you new a class, the generated code will properly set up the vtable. However, malloc will not properly initialize the vtable

要查看虚拟表,请运行 g ++ -fdump-class-hierarchy

To see the virtual table, run g++ -fdump-class-hierarchy

Vtable for Derived
Derived::_ZTV7Derived: 3u entries
0     (int (*)(...))0
8     (int (*)(...))(& _ZTI7Derived)
16    Derived::x

Class Derived
   size=16 align=8
   base size=12 base align=8
Derived (0x10209fc40) 0
    vptr=((& Derived::_ZTV7Derived) + 16u) <-- notice how this is part of the structure
  Base (0x10209fcb0) 0 nearly-empty
      primary-for Derived (0x10209fc40)

出于类似的原因,在不重载operator =的情况下,生成的汇编代码将仅复制数据,而不复制vtable [同样,编译器仅知道复制数据,而不复制vtable]

For a similar reason, without overloading operator=, the generated assembly code will only copy the data and not the vtable [again, the compiler only knows to copy the data, not the vtable]

如果要查看具有有效vtable函数的基于指针的版本:

If you want to see a pointer-based version with a valid vtable function:

Derived e(123);
d = &e;

  1. 对于非多态类型,我还需要使用new吗?

如果您使用的是虚函数,则可以,即使对于非多态类型也是如此

If you are using virtual functions, then yes, even for non-polymorphic types

  1. 我希望我的类需要的对齐方式是sizeof返回的类大小,以便使address_returned_by_malloc + i * sizeof(my_class)形式的任何地址都适合分配我的对象.

对齐方式不是问题.

这篇关于在C ++中,为什么需要new来动态创建对象而不是分配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆