Tro*_*lum 5 c++ malloc virtual-functions
可能重复:
C++:为什么new需要?
为什么我不能使用malloc为我的对象分配空间,因为它们是包含虚函数的类的子元素?这真令人沮丧.有充分的理由吗?
以下程序说明了这个问题.它在第27行的段错误,我称之为aa-> f()
#include <iostream>
#include <cstdlib>
class A
{
public:
virtual int f() {return 1;}
};
class B
{
public:
int f() {return 1;}
};
class Aa : public A {};
class Bb : public B {};
int main()
{
Aa* aa = (Aa*)malloc(sizeof(Aa));
Aa* aan = (Aa*)new Aa();
Bb* bb = (Bb*)malloc(sizeof(Bb));
std::cout << bb->f() << std::endl;
std::cout << aan->f() << std::endl;
std::cout << aa->f() << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
版本信息:g ++(Ubuntu/Linaro 4.4.4-14ubuntu5)4.4.5
malloc仅分配内存,但不创建对象.所以,这条线
Aa* aa = (Aa*)malloc(sizeof(Aa));
Run Code Online (Sandbox Code Playgroud)
分配一个足够大的内存区域来容纳一个A,但包含垃圾.正如其他人指出的那样,这也意味着vtable不会设置指针(我从@DavidRodríguez对另一个答案的评论得到了那个),这是调度虚拟函数所必需的.由于B不包含虚函数,因此不会出现这样的问题.B但是,如果B包含任何需要初始化的数据成员,也会发生这种情况,例如:
class B
{
public:
B() : foo(new int()) {}
int f() {return *foo;}
private:
int * foo;
};
Run Code Online (Sandbox Code Playgroud)
这条线
Aa* aan = (Aa*)new Aa();
Run Code Online (Sandbox Code Playgroud)
可以没有演员:
Aa* aan = new Aa();
Run Code Online (Sandbox Code Playgroud)
原因是malloc对C++构造函数一无所知,因此不会调用它们.您可以使用展示位置new自行调用构造函数:
int main()
{
Aa* aa = (Aa*)malloc(sizeof(Aa));
new(aa)Aa;
Aa* aan = (Aa*)new Aa();
Bb* bb = (Bb*)malloc(sizeof(Bb));
new(bb)Bb;
std::cout << bb->f() << std::endl;
std::cout << aan->f() << std::endl;
std::cout << aa->f() << std::endl;
aa->~Aa();
free(aa);
delete aan;
bb->~Bb();
free(bb);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
请注意,您必须在释放此类内存之前手动调用析构函数.