Question:
#include <iostream>
class T
{
int x;
public:
T() { std::cout << "constr\n"; }
~T() { std::cout << "destr\n"; }
};
int main (void)
{
char *buf = new char[sizeof(T)]; //13 line
T *t = new(buf) T;
t->~T();
}
What kind of memory allocation is new(buf)
? That is, memory is allocated in line 13, and then in line 14 new memory is not allocated for an object of type T
, but already allocated memory is taken from the one pointed to by buf
. That is, this method takes less actions, because you can allocate a lot of memory once and then use it with new(buf)
when dynamically allocating objects. If so, then the pointer will point to the next free memory cell of the allocated area, when there is, for example, one more allocation T *t2 = new(buf) T;
, i.e. buf points to a chunk of memory the size of class T and will therefore overwrite the memory pointed to by *t
. It's still not clear how it's implemented. Since new
is an operator, there is probably an overload of it, which takes a pointer to already allocated memory and the second parameter is the object to be allocated in it. In general, this is all guesswork and maybe I'm fundamentally wrong about this. So it would be best if you wrote what it is called, so that you could at least read somewhere about this method or explain it as you see fit.
Answer:
@mzarb , there's really no magic here. Everything is pretty simple. It is you who endow the language/compiler with some special properties.
Consider an example of your (slightly modified) program.
avp@avp-xub11:~/hashcode$ cat mzarb.cpp
#include <iostream>
#include <string.h>
class T
{
int x;
public:
T() { std::cout << "constr\n"; }
~T() { std::cout << "destr\n"; }
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 << '\n';
T *t = new(s.f1) T;
std::cout << "f2 after: " << s.f2 << '\n';
t->setX('z');
std::cout << "f2 again: " << s.f2 << '\n';
std::cout << "f2 offset: " << s.f2+2 << '\n';
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$
You see, everything is extremely transparent. Nobody checks anything. And reasoning about reliability and safety is in reality a "scam of suckers."
Yes, the cross compiler does a lot of checks and for them the language forces you to write (and learn) a lot of extra stuff.