C ++:为什么`new`需要的? [英] C++: why is `new` needed?
问题描述
我有这个简单的类层次结构:
类基地{
上市:
虚拟INT X()常量= 0;
};
类派生的:公共基础{
INT _x;
上市:
派生(INT X):_x(X){}
INT X()const的{返回_x; }
};
如果我用的malloc
分配的衍生
的实例,然后尝试访问该多态函数 X
,程序崩溃(我得到一个分段错误):
INT主要(){
衍生* D;
D =(导出*)malloc的(的sizeof(衍生));
* D =派生(123);
性病::法院<<的d-&X的催化剂()&其中;&其中;的std :: ENDL; //崩溃
返回0;
}
当然,我的实际应用是一个复杂得多(这是一个类型的内存池)。
我是pretty的肯定这是因为我分配的方式 D
:我没有使用新
。
我知道安置新
运营商,它必须是我所需要的,但我从来没有使用过它,并得到了一些问题:
-
为什么我的应用程序崩溃,如果我不使用
新
?这是什么
新
实际上做?为什么我不能只使用赋值运算符来分配
的(123)的值而得;
来指出由D <存储区域/ code>?
-
请问我需要使用
新
也非多态类型?如何POD的?
-
在 C ++ FAQ我联系上面该说,存储区域传递到安置
新
必须对准了我创建的对象。我知道对齐是什么,但我不知道如何检查需要我的课的定位。
的malloc
手册说:的malloc()和释放calloc()函数返回一个指针适合任何类型的变量排列分配的内存。
我希望,需要我的课的定位是作为sizeof的返回
的班级规模,使之在形式的任何地址
address_returned_by_malloc + I *的sizeof(my_class)
适用于分配我的对象。是我的希望吧?
让我们下去就行
- 为什么我的应用程序崩溃,如果我不使用新的?
虚拟表已损坏。
虚拟表所分配的内存之后卡住。当你新
一类,所产生的code将正确设置虚函数表。不过,malloc的不正确初始化虚函数表
要看到虚拟表,跑 G ++ -fdump类层次结构
V表的派生
衍生:: _ ZTV7Derived:3U项
0(中间体(*)(...))0
8(中间体(*)(...))(&安培; _ZTI7Derived)
16派生:: X
派生类
大小= 16 ALIGN = 8
底座尺寸= 12基地ALIGN = 8
派生(0x10209fc40)0
的vptr =((&安培;衍生:: _ ZTV7Derived)+ 16U)所述; - 注意这是怎么结构的一部分
基地(0x10209fcb0)0近空
初级的衍生(0x10209fc40)
出于同样的理由,没有超载运算符=,生成的程序集code时,只复制数据,而不是虚函数表[再次,编译器只知道复制数据,而不是虚函数表]
如果你想看到一个基于指针的版本有一个有效的虚函数表的功能:
派生E(123);
D =与评估;
- 在我需要使用新的也非多态类型?
如果您使用的是虚函数,那么,即使对于非多态类型
- 我希望,需要我的课的定位是为返回sizeof的班级规模,使之在形式address_returned_by_malloc + I *的sizeof(my_class)任何地址,适用于分配我的对象。
对齐是不是一个问题。
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; }
};
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).
I'm pretty sure it's because of the way I allocate d
: I didn't use new
.
I know of placement new
operator, which must be what I need, but I've never used it and have got some questions:
why is my application crashing, if I don't use
new
?What does
new
actually do?Why can't I just use the assignment operator to assign the value of
Derived( 123 );
to the memory area pointed byd
?Would I need to use
new
also for non-polymorphic types?How about POD ones?
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
manual says:The malloc() and calloc() functions return a pointer to the allocated memory that is suitably aligned for any kind of variable.
And I hope that the alignment needed for my class is the class size as returned by
sizeof
, so that any address in the formaddress_returned_by_malloc + i * sizeof(my_class)
is suitable to allocate my objects.Are my hopes right?
Let's go down the line
- why is my application crashing, if I don't use new?
Virtual table is corrupted.
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
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)
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]
If you want to see a pointer-based version with a valid vtable function:
Derived e(123);
d = &e;
- Would I need to use new also for non-polymorphic types?
If you are using virtual functions, then yes, even for non-polymorphic types
- 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.
Alignment is not an issue.
这篇关于C ++:为什么`new`需要的?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!