malloc()和虚函数有什么问题?

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

Dav*_*idK 7

实现虚函数的常用方法是在与对象的负偏移处具有指向"虚拟表"或vtable的指针.需要此表来确定要调用的虚函数.这就是为什么只有malloc'ing空间不起作用的原因.


Bjö*_*lex 6

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)


NPE*_*NPE 6

原因是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)

请注意,您必须在释放此类内存之前手动调用析构函数.