2

Let's consider I have a class Permission which is constructed with a username and a permission identifier. The constructor of this permission class will check if the user has that specific permission and throws if not.

Inside the api request handler, these permission objects are stack variables and constructed with a user and a permission. I expect a throw if there is no permission for that user.

Is there a guarantee that these permission objects won't be optimized out because I just construct them but never use them again (They need to throw if the permission is denied)?

Gustavo
  • 919
  • 11
  • 34
  • Just a remark; some people don't like exceptions being raised in constructors and/or throwing (expensive) exception for typical testing purposes. – Stefan Nov 22 '17 at 12:45
  • 2
    @Stefan: Those people are wrong. And I'm not going to call that subjective. C++ constructors and exceptions were designed hand in hand. For instance, the inability to return an error code from a constructor is justified by the fact that you throw exceptions instead of returning error codes. – MSalters Nov 22 '17 at 12:47
  • @MSalters: maybe that's why I never found a true satisfying answer backing their argument ;-) – Stefan Nov 22 '17 at 12:53

3 Answers3

2

Yes. Optimizations work by the as-if rule. The program has to behave as if it's running on a compliant C++ implementation. Now the particular "compliant behavior" might not always be what you expect from the actual hardware. E.g. the speed of a empty loop might be too fast for your CPU model, because the loop was optimized out.

However, every implementation must behave as if it calls your constructor. That does include inlining the constructor (no function call in assembly), but the actual content of the ctor, such as console I/O, still has to happen

MSalters
  • 173,980
  • 10
  • 155
  • 350
1

Is there a guarantee that these permission objects won't be optimized out because I just construct them but never use them again (They need to throw if the permission is denied)?

I believe that yes, per the "as-if-rule" (and the same guarantees apply to std::lock_guard which is generally used likewise).

Be sure to add some comment (since a side-effecting-only constructor might be very surprising, especially if the constructor normally don't do anything useful unless some exception is thrown).

a previous version of that answer mentioned volatile which is not relevant

BTW, compilers should not LTO-optimize such a code, but that might be an infrequent case, so you might check that they do not.

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 2
    @Stefan I was strongly considering downvoting, but then didn't. The reason is recommending `volatile`. That is not what `volatile` is for and it absolutely doesn't signal *"this object does something interesting in constructor or destructor"* to me. And if you need to add `volatile` here to fix your broken compiler you are just in a world of hurt that adding `volatile` will not fix. – nwp Nov 22 '17 at 13:02
  • I did improve that `volatile` is not necessary. But I strongly think that some annotation is required. – Basile Starynkevitch Nov 22 '17 at 13:04
  • Besides the use of `volatile`; I do believe the argument of an (unexpected-)side-effect-only-by-constructor-object is valid. I think it led OP to the question in the first place. – Stefan Nov 22 '17 at 13:08
  • 2
    I'd remove volatile from the answer altogether, it has nothing to do with this. If the annotation is needed, then it's bad design. If `Permission` does something important, it should do it with a proper function call, by a proper name, not "hidden" in the constructor. – geza Nov 22 '17 at 13:34
1

Yes. Optimizations are mostly based on the "as-if-rule", meaning a compiler can do whatever it wants as long as the result behaves as if the compiler had strictly followed the standard and not done any optimizations.

The optimization in question would change the behavior (exception thrown vs not thrown) so it is not allowed. Unless of course you have some UB in the code because then strictly following the standard becomes irrelevant (no guarantees whatsoever).

nwp
  • 9,623
  • 5
  • 38
  • 68