Arijit posted:
JKop said:
[snip]
std::string* strings = malloc( 10 * sizeof(std::string) );
new(&strings[0]) std::string;
new(&strings[1]) std::string;
new(&strings[2]) std::string;
new(&strings[3]) std::string;
new(&strings[4]) std::string;
new(&strings[5]) std::string;
new(&strings[6]) std::string;
new(&strings[7]) std::string;
new(&strings[8]) std::string; new(&strings[9]) std::string;
I don't think explicit calling of constructors is allowed, though I
could be wrong.
You are. Some people's explanation of "placement new" is that it constructs
an object at a particular place in memory. My own explanation of it is that
is calls constructors.
Out of curiosity, if it were illegal to explicitly call a constructor, then
what is the function of "placement new"?
strings[0].~std::string(); strings[1].~std::string();
strings[2].~std::string(); strings[3].~std::string();
strings[4].~std::string(); strings[5].~std::string();
strings[6].~std::string(); strings[7].~std::string();
strings[8].~std::string(); strings[9].~std::string();
Don't do this. Explicit calling of destructors is allowed for a very
special reason, and it should not be abused.
My code does not "abuse". My code:
A) Allocates memory
B) Calls constructor
C) Calls destructor
D) Deallocates memory
The only place where my above code could fall down is if an object of the
class "std::string" had to reside in a particular place in memory, like at a
boundary or whatever.
As to there being a very special reason, my code *is* that very special
reason - I'm doing everything manually. I'm allocating the memory by myself,
I'm calling the constructor by myself, and I'm calling the destructor by
myself, etc.
Here's actually a nice use for it:
void SomeFunc(int const a)
{
//This function will define an object of type "std::string".
//The particular constructor it calls is dependent upon
//the supplied argument "a".
//This can be achieved with dynamic memory allocation:
std::string* p_str;
switch (a)
{
case 1:
p_str = new std::string(... // a particular constructor
break;
case 2;
p_str = new std::string(... // a different constructor
break;
... //and so on
}
//Work with the string
//Finished working with the string
delete p_str;
}
Ofcourse, in the above, the dynamic memory allocation is unnecessary.
void SomeFunc(int const a)
{
char blah[ sizeof(std::string) ];
switch (a)
{
case 1:
new(blah) std::string(...
break;
case 2:
new(blah) std::string(...
...
}
std::string& str = *reinterpret_cast< std::string* const > ( static_cast
<char* const>(blah) );
//Now we can use "str" just like an "std::string"
...
//Cleanup time:
str.~std::string();
}
-JKop