2
result_t work(resource_t& resource) {
    lock_t ___(resource);

    return work_impl(resource);
}

Is it guaranteed that the destructor of ___ will be called AFTER work_impl() returned? Or is the compiler free to destroy ___ before calling work_impl()?

Joker_vD
  • 3,715
  • 1
  • 28
  • 42
  • 5
    Names that contain two or more consecutive underscores are reserved for use by the implementation. Don't use them. – Pete Becker Nov 05 '13 at 14:03
  • @PeteBecker I wish there was a way to declare an object without naming it, so that the object will be destroyed at the end of the block. Sadly, unnamed objects are destroyed on the spot. – Joker_vD Nov 05 '13 at 14:06
  • @PeteBecker Aren't they still undefined behavior (or is some sort of diagnostic required)? – James Kanze Nov 05 '13 at 14:07
  • @JamesKanze - without digging into the details, yes, I'm pretty sure the behavior is undefined. There is no diagnostic required; it would, in general, not be possible to diagnose. – Pete Becker Nov 05 '13 at 14:09
  • No, they are not. They are "reserved to the implementation", and the effect of their use is implementation-defined, not undefined. – Sneftel Nov 05 '13 at 14:10
  • @Ben - "implementation defined" means the the implementation must document what happens. There is no such requirement for reserved identifiers. There are no requirements on the behavior of a program that uses reserved identifiers; that makes the behavior of such a program undefined. – Pete Becker Nov 05 '13 at 14:19
  • @PeteBecker it is undefined as per `17.6.4.3` *Reserved names*. – Shafik Yaghmour Nov 05 '13 at 14:35

4 Answers4

4

Expression work_impl(resource) will be executed, the result will be copied to caller side or used as a temporary. Then, Object ___ will be destructed.

On the other hand, DON'T use __ or ___ as prefix of any identifier. They're reserved for compiler.

masoud
  • 55,379
  • 16
  • 141
  • 208
  • 1
    It will be destructed _after_ the results of the expression have been copied to where ever the compiler puts return values. (In this case, of course, RVO may mean that there is no such copy. But conceptually, it is there.) – James Kanze Nov 05 '13 at 14:06
2

If the destructor is non-trivial, it may not be called prematurely, provided that the rest of the code is correct. In case of undefined behavior (say, a variable name with two or more adjacent _), of course, there are no guarantees.

James Kanze
  • 150,581
  • 18
  • 184
  • 329
1

The compiler is free to do whatever it likes if there's no way to tell the difference. But if the destructor has some program-visible effect, it will always happen AFTER work_impl returns.

Sneftel
  • 40,271
  • 12
  • 71
  • 104
1

The behavior of this program is actually undefined, the identifier __ is reserved and we can see from the draft C++ standard 17.6.4.3 Reserved names paragraph 2 says:

If a program declares or defines a name in a context where it is reserved, other than as explicitly allowed by this Clause, its behavior is undefined.

and if we look further to section 17.6.4.3.2 Global names which says:

Each name that contains a double underscore _ _ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.

so unless the compiler documents that __ is free to be used by user code then it is reserved.

Destructors are invoked implicitly

So if this program did not invoke undefined behavior the rules for destructors that are invoked implicitly can be taken from the draft standard section 12.4 Destructotrs paragraph 11 which says (emphasis mine)

— for constructed objects with static storage duration (3.7.1) at program termination (3.6.3),

— for constructed objects with thread storage duration (3.7.2) at thread exit,

for constructed objects with automatic storage duration (3.7.3) when the block in which an object is created exits (6.7),

— for constructed temporary objects when the lifetime of a temporary object ends (12.2),

so that means the destructor for an automatic object will be invoked when you exit work(), which has to happen after the results are returned. We can see further that the order of objects are destroyed in is also specified from 6.6 Jump statements:

On exit from a scope (however accomplished), objects with automatic storage duration (3.7.3) that have been constructed in that scope are destroyed in the reverse order of their construction. [ Note: For temporaries, see 12.2. —end note ]

Note that names that contain a double underscore __, or start with either an underscore followed by an uppercase letter are reserved in any scope.

Community
  • 1
  • 1
Shafik Yaghmour
  • 154,301
  • 39
  • 440
  • 740
  • The use of these identifiers, however, IS "explicitly allowed by the clause". 17.6.4.3.2 says that these identifiers are reserved to the implementation "for any use". The implementations are therefore free to gift them back to user code. It is common, for instance, for implementations to expose certain identifiers of this type for user code to control various aspects of the runtime libraries. If the user code could not declare these symbols or include headers which declared them, they could not use them in compliant code. – Sneftel Nov 05 '13 at 15:02
  • @Ben there is no indication that this is the case here and I am not aware of any instances of this, if you can show me some I would be interested in seeing them. I mean `gcc` and `clang` do have some odd corners so it would not super surprising if such a case existed. But it does have to be documented for its use to be valid. – Shafik Yaghmour Nov 05 '13 at 15:05
  • Just glancing at some random source files, `__crtDebugFillThreshold` in the Visual C++ runtime library, and `__free_hook` in GLIBC. – Sneftel Nov 05 '13 at 15:12
  • Though you're right, there's no indication that the asker's particular implementation has freed `___` for their use, and better safe than sorry. – Sneftel Nov 05 '13 at 15:13
  • @Ben well `gcc` and `Visual C++` are the implementation but user land code is not allowed to create variables with those names, although once the variables are created by the implementation and it is documented it is valid for user land code to use them. – Shafik Yaghmour Nov 05 '13 at 15:18
  • The standard doesn't say anything about creating or using them, only about declaring or defining them. And they can't be used unless they're declared in user land code. – Sneftel Nov 05 '13 at 15:22
  • @Ben the compiler and associated libraries are not user land code, it is implementation and therefore falls under the *reserved for implementation* clause in `17.6.4.3.2` so if GLIBC delcares `_free_hook` that is fine b/c it is the implementation. – Shafik Yaghmour Nov 05 '13 at 15:30
  • @Joker_vD I think a lot of people are surprised by that, I previously [covered rules for identifiers](http://stackoverflow.com/questions/15285787/can-you-start-a-class-name-with-a-numeric-digit/15285827#15285827) and [this thread](http://stackoverflow.com/questions/9996909/does-using-leading-underscores-actually-cause-trouble) has some examples of how this can cause pain. Just don't start your identifiers with `_`. – Shafik Yaghmour Nov 05 '13 at 18:02