The "as-if rule" gives the compiler the right to optimize out or reorder expressions that would not make a difference to the output and correctness of a program under certain rules, such as;
§1.9.5
A conforming implementation executing a well-formed program shall produce the same observable behavior as one of the possible executions of the corresponding instance of the abstract machine with the same program and the same input.
The cppreference url I linked above specifically mentions special rules for the values of volatile objects, as well as for "new expressions", under C++14:
New-expression has another exception from the as-if rule: the compiler may remove calls to the replaceable allocation functions even if a user-defined replacement is provided and has observable side-effects.
I assume "replaceable" here is what is talked about for example in
§18.6.1.1.2
Replaceable: a C++ program may define a function with this function signature that displaces the default version defined by the C++ standard library.
Is it correct that mem
below can be removed or reordered under the as-if rule?
{
... some conformant code // upper block of code
auto mem = std::make_unique<std::array<double, 5000000>>();
... more conformant code, not using mem // lower block of code
}
Is there a way to ensure it's not removed, and stays between the upper and lower blocks of code? A well placed volatile (either/or volatile std::array or left of auto) comes to mind, but as there is no reading of mem
, I think even that would not help under the as-if rule.
Side note; I've not been able to get visual studio 2015 to optimize out mem
and the allocation at all.
Clarification: The way to observe this would be that the allocation call to the OS comes between any i/o from the two blocks. The point of this is for test cases and/or trying to get objects to be allocated at new locations.
make_unique
creates a new object, and as far as I know C++ compilers do not optimize out object creation due to the potential for side effects. They may elide unnecessary constructor calls, but they always ensure at least one is called. Otherwise, code that uses objects for RAII having constructors with side effects could not safely rely on that pattern without the inclusion of memory barriers. – Oeilladestd::array
as the example? I thought that it doesn't usenew
. Or is it allowed to usenew
internally? Then that class would be pretty useless IMO. – Mobilityvolatile
in here goes:new volatile int(10)
. The spec says that access to volatiles is the observable side effect. Not the call to the allocation function. So the compiler is still allowed to omit the call to the allocation function if it arranges to allocate the memory elsewhere!? Only judging by that cppreference quote.. I have not looked up the spec about it. – Mobility