With the as-if rule, compiler is allowed to do any optimization as long as observable behavior is identical.
Freeing immediately q/p would not be allowed, as then you will use dangling pointer.
Though it can call destructor before end of scope:
{ int* p = new int(0); std::unique_ptr<int> q(p); ... // make use of 'p' ... // No longer use of p (and q) ... // Ok, can delete p/q now (as long there are no observable behaviors changes) ... }
As operator new/delete might be changed globally, compiler would generally not have enough information (linker has though), so consider they have (potentially) observable behaviors (as any external functions).
c++14 allows some elisions/optimisation of new expression, so
{ delete new int(42); int* p1 = new int(0); int* p2 = new int(0); std::unique_ptr<int> q2(p2); std::unique_ptr<int> q1(p1); ... // make use of 'p1'/p2 ... }
Can be "replaced" by
{ // delete new int(42); // optimized out std::unique_ptr<int[]> qs{new int [] {0, 0}}; // only one allocation instead of 2 int* p1 = q->get(); int* p2 = q->get() + 1; ... // make use of 'p1'/p2 ... }
newanddeleteoperators aren't observable behavior since C++14, IIRC.