views:

101

answers:

2

With reference to the discussion here

$3.7.1/2 - "If an object of static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy may be eliminated as specified in 12.8."

$12.8/15- "When certain criteria are met, an implementation is allowed to omit the copy construction of a class object, even if the copy constructor and/or destructor for the object have side effects."

Is the above case, specific examples of a case, where even a volatile read/write may also be optimized away (e.g. if a copy constructor has a read/write to a volatile variable).

So the question is "can a copy constructor be elided even if the copy constructor has a read/write of a volatile variable?"

A: 

NRVO is only allowed if the named object is non-volatile [its right in the same section you quoted, the first bullet], but otherwise I don't see why not. After all, if the object you are creating is volatile, you are still writing to it, you just aren't doing so via the copy constructor. And it doesn't qualify which side effects it is allowed to ignore, so clearly if the volatile read/write is within the copy constructor itself the compiler doesn't have to care.

Dennis Zickefoose
@Dennis Zickefoose: I meant a case where the class object is non cv-qualified, but the copy constructor does a read/write to global/namespace scope volatile variable. In this case, is the compiler is allowed to elide away the copy constructor as the Standard says. But why? Why is the side effect of copy constructor (updating the volatile variable e.g.) not a deterrant for eliding away the copy constructor?
Chubsdad
@chubs: Because side effects are never deterrents for eliding copy constructors. The compiler often doesn't even know what side effects there might be when it decides to elide the copy, so in general it can't take this information into account.
Dennis Zickefoose
A: 

Sometimes. Funny you should ask, since something I mis-remembered about volatile (which Johannes called out) led me to look up exactly such trivia.

§12.8/15:

in a return statement in a function with a class return type, when the expression is the name of a non-volatile automatic object with the same cv-unqualified type as the function return type, the copy operation can be omitted by constructing the automatic object directly into the function’s return value

So, it's OK to eliminate a volatile access by eliding the constructor, but not if the entire object is volatile.

Also, it can make a difference if a function returns volatile foo by value as opposed to plain foo, because construction of the volatile temporary cannot be elided!

foo factory_a(); // return class by value
const foo factory_b(); // also return by value: rather pointless
volatile foo factory_c(); // implies no elision

Note that the cv-qualification of the returned temporary also affects access semantics of the temporary, for example factory_b().non_const_method() is illegal. So this is all more arcane than boneheaded.

Potatoswatter