在C ++中,为什么需要new来动态创建对象而不是分配? [英] In C++, why is `new` needed to dynamically create an object rather just allocation?
问题描述
我有这个简单的类层次结构:
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.
我的希望对吗?
推荐答案
让我们走下去
- 如果我不使用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;
- 对于非多态类型,我还需要使用new吗?
如果您使用的是虚函数,则可以,即使对于非多态类型也是如此
If you are using virtual functions, then yes, even for non-polymorphic types
- 我希望我的类需要的对齐方式是sizeof返回的类大小,以便使address_returned_by_malloc + i * sizeof(my_class)形式的任何地址都适合分配我的对象.
对齐方式不是问题.
这篇关于在C ++中,为什么需要new来动态创建对象而不是分配?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!