0

我正在尝试用 malloc 和 free 替换 operator new 和 delete (我有理由这样做)。问题如下面的代码所示:

std::string *temp = (std::string *)malloc(sizeof(std::string) * 2); // allocate space for two string objects.
temp[0] = "hello!";
temp[1] = "world!";
for(int i = 0; i < 2; i++)
{
    printf("%s\n", temp[i].c_str());
}
free(temp);
return 0; // causes SIGSEGV.

然而..

std::string *temp = new std::string[2];
temp[0] = "hello!";
temp[1] = "world!";
for(int i = 0; i < 2; i++)
{
    printf("%s\n", temp[i].c_str());
}
delete [] temp;
return 0; // works fine

为什么?谁能建议我用 malloc 和 free 替换这些运算符的正确方法是什么?

问候。

编辑:这只是示例,我没有使用标准 C++ 库。

编辑:这样的事情呢?

class myclass
{
    public:
        myclass()
        {
            this->number = 0;
        }
        myclass(const myclass &other)
        {
            this->number = other.get_number();
        }
        ~myclass()
        {
            this->number = 0;
        }
        int get_number() const
        {
            return this->number;
        }
        void set_number(int num)
        {
            this->number = num;
        }
    private:
        int number;
};

int main(int argc, char *argv[])
{
    myclass m1, m2;
    m1.set_number(5);
    m2.set_number(3);

    myclass *pmyclass = (myclass *)malloc(sizeof(myclass) * 2);

    pmyclass[0] = myclass(m1);
    pmyclass[1] = myclass(m2);

    for(int i = 0; i < 2; i++)
    {
        printf("%d\n", pmyclass[i].get_number());
        pmyclass[i].myclass::~myclass();
    }

    free(pmyclass);

    return 0;
}
4

3 回答 3

7

malloc并且free不要调用 C++ 类的构造函数和析构函数。它也不存储有关数组中分配的元素数量的信息(就像您正在做的那样)。这意味着内存只是被分配但从未初始化。但是,您仍然可以手动构造和销毁对象。

您应该首先使用placement-new构造对象。这要求您将 a 指针传递到要创建对象的位置,并指定需要实例化的对象的类型。例如,将字符串文字分配给已分配(但未初始化)的字符串对象的第一行如下所示:

new(&temp[0]) std::string("hello!");

一旦你完成了字符串,你需要通过直接调用它们的析构函数来销毁它们。

temp[0].std::string::~string();

您提交的代码如下所示:

// allocate space for two string objects.
std::string *temp = (std::string *)malloc(sizeof(std::string) * 2); 

// Using placement-new to constructo the strings
new(&temp[0]) std::string("hello!");
new(&temp[1]) std::string("world!");

for (int i = 0; i < 2; i++)
{
    printf("%s\n", temp[i].c_str());
}

//  Destroy the strings by directly calling the destructor
temp[0].std::string::~string();
temp[1].std::string::~string();
free(temp);
于 2013-10-12T23:15:42.590 回答
4

如果你真的想进入这个兔子洞......好吧,你需要放置新的并且你需要手动调用析构函数。看起来是这样的:

#include <string>
#include <stdlib.h>
#include <stdio.h>

int main()
{
    std::string *temp = (std::string *)malloc(sizeof(std::string) * 2); // allocate space for two string objects.
    new (&temp[0]) std::string("hello!");
    new (&temp[1]) std::string("world!");
    for(int i = 0; i < 2; i++)
    {
        printf("%s\n", temp[i].c_str());
    }
    temp[1].std::string::~string();
    temp[0].std::string::~string();
    free(temp);
    return 0;
}

由于malloc给您一个未初始化的内存块,您需要在适当的内存槽中构造对象,并且在释放内存之前,您必须手动销毁它们。

于 2013-10-12T23:15:18.910 回答
2

您想实现自己的operator new()with malloc,而不是替换operator newwith malloc

要实现operator new(),只需像使用任何其他函数一样编写它。

void* operator new() (size_t sz) { return malloc(sz); }

如果您想要一个失败的标准兼容版本std::bad_alloc,只需为此插入您的代码。

operator delete留给读者作为练习, 和 也是operator new[]()如此operator delete[]()

于 2013-10-13T13:55:03.467 回答