开发者

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, then
  • class 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);
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜