#include
class T
{
int x;
public:
T() { std::cout << "constr
"; }
~T() { std::cout << "destr
"; }
};
int main (void)
{
char *buf = new char[sizeof(T)]; //13 line
T *t = new(buf) T;
t->~T();
}
Что это за выделение памяти такое new(buf)? То есть память выделяется в строчке 13, а потом в строчке 14 не выделяется новая память под объект типа T, а берется уже выделенная память из той, на которую указывает buf. То есть такой способ занимает меньше действий, потому как можно раз выделить много памяти и потом использовать её с помощью new(buf) при динамическом выделении объектов. Если это так, то указатель будет указывать на следующий свободную ячейку памяти выделенного участка, когда будет к примеру ещё одно выделение T *t2 = new(buf) T;, то есть buf указывает на участок памяти размером с размер класса T и по этому перезапишет память, на которую указывает *t. И ещё не понятно как это реализовано. Так как new - это оператор, то наверное есть его перегруженная версия, которая принимает указатель на уже выделенную память и вторым параметром объект, который нужно выделить в ней.
Вообщем это все догадки и возможно я кардинально не прав по этому поводу. Так что лучше всего было бы, если бы вы написали как это называется, что бы можно было хоть почитать где нибудь об этом способе или объяснили так, как вы считаете нужным.
Ответ
@mzarb, на самом деле никакой магии тут нет. Все довольно просто. Это Вы наделяете язык/компилятор какими-то особыми свойствами.
Разберите пример Вашей (немного измененной) программы.
avp@avp-xub11:~/hashcode$ cat mzarb.cpp
#include
class T
{
int x;
public:
T() { std::cout << "constr
"; }
~T() { std::cout << "destr
"; }
void setX(int v) { x = v; }
};
int main (void)
{
struct {
char f1[2];
char f2[10];
} s;
strcpy (s.f2,(char *)"1234");
std::cout << "f2 before: " << s.f2 << '
';
T *t = new(s.f1) T;
std::cout << "f2 after: " << s.f2 << '
';
t->setX('z');
std::cout << "f2 again: " << s.f2 << '
';
std::cout << "f2 offset: " << s.f2+2 << '
';
t->~T();
}
avp@avp-xub11:~/hashcode$ g++ mzarb.cpp
avp@avp-xub11:~/hashcode$ ./a.out
f2 before: 1234
constr
f2 after: 1234
f2 again:
f2 offset: 34
destr
avp@avp-xub11:~/hashcode$
Видите, все предельно прозрачно. Никто ничего не проверяет. А рассуждения о надежности и безопасности это в реальности "развод лохов".
Да, крестовый компилятор делает много проверок и для них язык заставляет Вас писать (и изучать) кучу лишнего.
Комментариев нет:
Отправить комментарий