Я пытаюсь заменить оператор new и удалить с помощью malloc и бесплатно (у меня есть причины для этого). Проблема приведена в коде ниже:
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 и бесплатно?
С уважением.
EDIT: это просто пример, я не использую стандартную библиотеку C++.
EDIT: как насчет этого?
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;
}
Вы хотите реализовать собственный operator new()
с помощью malloc
, а не для замены operator new
на malloc
.
Чтобы реализовать operator new()
, просто напишите его так же, как и с любой другой функцией.
void* operator new() (size_t sz) { return malloc(sz); }
Если вы хотите стандартную версию, которая бросает std::bad_alloc
при сбое, просто вставьте свой код для этого.
operator delete
остается как упражнение для читателя, и поэтому operator new[]()
и operator delete[]()
.
malloc
и free
не вызывают конструктор и деструктор классов C++. Он также не хранит информацию о количестве элементов, выделенных в массиве (например, вы делаете). Это означает, что память просто назначается, но никогда не инициализируется. Однако вы все же можете вручную сконструировать и уничтожить объект.
Вы должны начать с создания объекта, используя place-new. Это требует, чтобы вы передали указатель на место, где должен быть создан объект, и указать тип объекта, который должен быть создан. Например, первая строка, в которой вы назначаете строковый литерал для выделенного (но неинициализированного) строкового объекта, выглядит следующим образом:
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);
Если вы действительно хотите спуститься в эту кроличью нору... ну, вам нужно место новое, и вам нужно вызвать деструкторов вручную. Вот как это выглядит:
#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
предоставляет вам неинициализированный блок памяти, вам нужно построить объекты в соответствующих слотах памяти и, прежде чем освобождать память, вы должны вручную их уничтожить.