5

When should one add the noexcept attribute to a function? i.e. when is the compiler not able to tell a function throws? Should everything be marked or is there a way to tell?

I'm not a fan of premature optimization, and I'm not a fan of premature attribution. I don't know of a way to "profile" the need of noexcept the same way I profile performance when optimizing.

When evaluating where it is necessary, please comment on the most common compilers, e.g. MSVC, GCC, etc.

Acorn
  • 24,970
  • 5
  • 40
  • 69
j__
  • 632
  • 4
  • 18
  • Please note that https://stackoverflow.com/questions/10787766/when-should-i-really-use-noexcept is talking about semantics but not necessity or use. (and also is dated) – j__ Sep 03 '20 at 16:32
  • 1
    It talks about necessity, too. For example: https://stackoverflow.com/a/12560616/1625187 This question looks like a dupe to me. – Evg Sep 03 '20 at 16:38
  • Related: https://stackoverflow.com/questions/63727438/is-noexcept-useless-when-not-throwing-is-zero-cost – j__ Sep 03 '20 at 16:39

2 Answers2

5

The C++ Core Guidelines recommends basically use it everywhere that the code doesn't throw. This is mostly important for libraries because code checkers use the functions you call to see if it's noexcept, otherwise you get a cascade of warnings.

That said, the most important recommendations are to make swap, move, and destructors noexcept.

The C++ Core Guidelines also recommends making default constructors noexcept which is great in general, but many patterns (like the pImpl idiom) often allocate memory in their default constructor. Therefore, I generally use noexcept on default constructors (or constructors that only take defaulted parameters), but if I know it can throw I make a point of explicitly marking it nothrow(false).

If you declare a default constructor, copy constructor, assignment operator, move constructor, move operator, or destructor to be =default it's implicitly noexcept. All destructors are also implicitly noexcept.

There's a notion that you can mark something noexcept to mean "if this does throw, go ahead and crash". I find this notion a bit wooly so in my code I mark things that can throw noexcept(false) or leave it unspecified. That's usually stuff that calls new or initializes std containers.

Chuck Walbourn
  • 38,259
  • 2
  • 58
  • 81
0

When should one add the noexcept attribute to a function?

Whenever you want to document and enforce that a function never throws.

It is important to recall that a mistake here means there will be a call to std::terminate() instead of propagating the exception. Due to this, it can be a pessimization.

i.e. when is the compiler not able to tell a function throws?

It is the opposite: the compiler has to assume everything throws unless it can prove otherwise (or is told otherwise).

It will be able to prove it when it has the required definitions. For instance, between TUs without LTO, it won't.

I don't know of a way to "profile" the need of noexcept

Like in any other case: you measure with and without.

For most projects, working on enabling LTO is a better way to deal with it.

Acorn
  • 24,970
  • 5
  • 40
  • 69