Can calls to memory allocation and constructor be interleaved with other operations required to perform a "new" expression?
Suppose I have a following class:
class Sample {
public:
Sample( int ) {}
};开发者_如何学Python
some function returning an int
int SomeFunction()
{
return 0;
}
and this code:
Sample* sample = new Sample( SomeFunction() );
Now I expect the following sequence:
SomeFunction()
is run, then::operator new()
is run to allocate memory for the object, thenclass Sample
constructor is run over allocated memory
Is this order fixed or can it be changed by an implementation such that say first memory is allocated, then SomeFunction()
is called, then constructor is run? In other words, can call to operator new()
function and call to class constructor be interleaved with anything?
The order is unspecified. [5.3.4]/21 reads:
Whether [operator new] is called before evaluating the constructor arguments or after evaluating the constructor arguments but before entering the constructor is unspecified. It is also unspecified whether the arguments to a constructor are evaluated if [operator new] returns the null pointer or exits using an exception.
The order of the calls to operator new and SomeFunction is unspecified - so it may change based on optimisation settings, compiler version, etc.
The constructor call I think has to come last.
Yes, it could be interleaved.
class A
{
public:
A(int i)
{
cout << "constructor" << endl;
}
void* operator new(size_t size)
{
cout << "new" << endl;
return malloc(size);
}
void operator delete(void*, size_t)
{
cout << "delete" << endl;
}
};
int f()
{
cout << "f()" << endl;
return 1;
}
int main()
{
A* a = new A(f());
}
Output:
new
f()
constructor
Though not guaranteed by the standard, compilers do have a reason to allocate memory first. If memory allocation fails, the constructor won't be called at all. So evaluating constructor arguments too early is probably not a good idea.
Actually, what I think happens is:
- new is used to allocate raw memory
- SomeFunction() is called returning a value X
- the constructor is called, with X as a a parameter
but I could be wrong. I would say that this shows that you shouldn't be worrying about the order.
You can't change what happens when you run that line of code. You can run some different lines of code.
void * p = ::operator new (sizeof (SomeFunction));
SomeFunction temp;
SomeFunction* sample = new (p) SomeFunction(temp);
精彩评论