Starting from C++14 we have allocation elision, allowing the implementations to omit calling allocation and deallocation functions. But it was a surprise to me to find what can trigger that kind of optimization in Visual Studio 2022.
In this program
struct A {};
bool x = ( delete new A, 0 );
there is no allocation elision and both new and delete operators are executed in the assembly:
bool x DB 01H DUP (?)
void `dynamic initializer for 'x''(void) PROC
sub rsp, 40
mov ecx, 1
call void * operator new(unsigned __int64)
mov edx, 1
mov rcx, rax
call void operator delete(void *,unsigned __int64)
mov BYTE PTR bool x, 0
add rsp, 40
ret 0
void `dynamic initializer for 'x''(void) ENDP
Online demo: https://godbolt.org/z/ozrW9Meqh
But if one defines class-specific operator delete in A:
struct A {
constexpr void operator delete(void *p) {
if(p)
::operator delete(p);
}
};
bool x = ( delete new A, 0 );
then allocation elision takes place and assembly code becomes simply
bool x DB 01H DUP (?)
without any dynamic initializer for 'x'. Online demo: https://godbolt.org/z/K4GvnrTT5
Why did adding class specific deallocation function trigger allocation elision? What are other known ways to achieve it?