Know your assembly

Consider this simple code snippet, where we call copy constructor on an uninitialized piece of memory:

void CopyConstruct0(int* mem, int orig)
{
    new (mem) int(orig);
}

I didnt really bother with creating special version of this routine for fundamental types, after all this version:

void CopyConstruct1(int* mem, int orig)
{
    *mem = orig;
} 

should result in same code as the one above, right? WRONG. In the first case compiler (MSVC) tests memory against null first. Resulting code:

mov    eax, DWORD PTR _mem$[esp-4]
test   eax, eax
je     SHORT $LN3@CopyConstr
mov    ecx, DWORD PTR _orig$[esp-4]
mov    DWORD PTR [eax], ecx
$LN3@CopyConstr: 

CopyConstruct1:

mov    eax, DWORD PTR _orig$[esp-4]
mov    ecx, DWORD PTR _mem$[esp-4]
mov    DWORD PTR [ecx], eax 

So it’s worth to fallback to quicker case where possible. (yeah, the difference isnt big, but it adds).

Old comments

ed 2008-03-14 19:29:52

That’s interesting. I couldn’t find any information why this happens except this one “If the memory allocation fails (operator new returns a value of 0), no initialization is performed” (from MSDN site).
If you try this code:
void CopyConstruct0(int* mem, int orig)
{
new int( orig)
}
You will get the same “null ptr check” as above.

admin 2008-03-15 11:25:07

It makes some sense, once you think about it. Test’s there so that sequence of calls:
void* mem = operator new(sizeof(X));
return new (mem) X(x);
works properly even if the allocation fails. (which is pretty much what y = new X(x) does…)

ed 2008-03-16 12:43:10

Yes, this make sense, since constructor should be called on a valid memory. This reminds me disscussion on a polish forum about “constructor vs Initialize” and this behaviour shows that “Initialize” will be slightly better for an objects that have already allocated memory (like in LIP).

therealremi 2008-03-16 16:00:02

“If the allocation function returns null, initialization shall not be done, the deallocation function shall not be called, and the value of the new-expression shall be null.”
Yes - really surprising that the compiler follows a standard ;)
BTW ed, the discussion was about â??constructor vs (constructor+Initialize)â? to be precise.

admin 2008-03-16 18:49:22

The fragment you quote is about ‘new expression’ (ie complete type construction), not about placement new itself. In theory, the check can be in there just in case of expression new, after calling allocation function, not in case of every placement new.

therealremi 2008-03-16 19:39:39

Now I have only a draft of the C++ standard on my disc so I won’t qoute it. But it states that the “placement new” you are refering to is just an extra form of the “new expression” (which calls the placement form of operator new as its allocation function).