When Should I Really Use Noexcept

When should I really use noexcept?

I think it is too early to give a "best practices" answer for this as there hasn't been enough time to use it in practice. If this was asked about throw specifiers right after they came out then the answers would be very different to now.

Having to think about whether or not I need to append noexcept after every function declaration would greatly reduce programmer productivity (and frankly, would be a pain).

Well, then use it when it's obvious that the function will never throw.

When can I realistically expect to observe a performance improvement after using noexcept? [...] Personally, I care about noexcept because of the increased freedom provided to the compiler to safely apply certain kinds of optimizations.

It seems like the biggest optimization gains are from user optimizations, not compiler ones due to the possibility of checking noexcept and overloading on it. Most compilers follow a no-penalty-if-you-don't-throw exception handling method, so I doubt it would change much (or anything) on the machine code level of your code, although perhaps reduce the binary size by removing the handling code.

Using noexcept in the big four (constructors, assignment, not destructors as they're already noexcept) will likely cause the best improvements as noexcept checks are 'common' in template code such as in std containers. For instance, std::vector won't use your class's move unless it's marked noexcept (or the compiler can deduce it otherwise).

When should one explicitly attribute noexcept?

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.

Should I use noexcept for simple functions that obviously cannot throw?

But if it's obvious (even to the compiler) that the function will never throw, why use noexcept at all?

That knowledge can be only inferred by knowing the definition of the function. The callers will likely include only the header, which contains the declaration. No information there. Your best chance is that the link time optimizer notices the implicit noexcept property and removes the exception handling (talking purely about theoretical considerations, not sure if compilers actually do this...).

This, of course, it's not possible in several circumstances, for example if you use your object polymorphically. Though your implementation is implicity noexcept, the function of the subclass might very well throw.

As a sidenote, life is usually fine and dandy without noexcept, so unless there's a specific reason you want to use it, e.g. a public API, a performance sensitive tight loop, coding standards, etc. you're free to omit it. Do not micro optimize or waste time.

How to use noexcept in C++ or How does it work?

A noexcept specification on a function is merely a method for a programmer to inform the compiler whether or not a function should throw exceptions.

The compiler can use this information to enable certain optimizations on non-throwing functions as well as enable the noexcept operator, which can check at compile time if a particular expression is declared to throw any exceptions.

For example, containers such as std::vector will move their elements if the elements' move constructor is noexcept, and copy otherwise (unless the copy constructor is not accessible, but a potentially throwing move constructor is, in which case the strong exception guarantee is waived).

noexcept is an improved version of throw(), which is deprecated in C++11. Unlike throw(), noexcept will not call std::unexpected and may or may not unwind the stack, which potentially allows the compiler to implement noexcept without the runtime overhead of throw().

For more details, please visit below websites

  • https://akrzemi1.wordpress.com/2014/04/24/noexcept-what-for/
  • When should I really use noexcept?

Edit: Sample source code to illustrate above points.

// whether foo is declared noexcept depends on if the expression
// T() will throw any exceptions, check in compile time
template <class T>
void foo() noexcept(noexcept(T())) {
}

void bar() noexcept(true) {
}

void baz() noexcept {
throw 42;
} // noexcept is the same as noexcept(true)

int main()
{
foo<int>(); // noexcept(noexcept(int())) => noexcept(true), so this is fine

bar(); // fine
baz(); // compiles, but at runtime this calls std::terminate
}

What is noexcept useful for?

The primary use of noexcept is for generic algorithms, e.g., when resizing a std::vector<T>: for an efficient algorithm moving elements it is necessary to know ahead of time that none of the moves will throw. If moving elements might throw, elements need to be copied instead. Using the noexcept(expr) operator the library implementation can determine whether a particular operation may throw. The property of operations not throwing becomes part of the contract: if that contract is violated, all bets are off and there may be no way to recover a valid state. Bailing out before causing more damage is the natural choice.

To propagate knowledge about noexcept operations do not throw it is also necessary to declare functions as such. To this end, you'd use noexcept, throw(), or noexcept(expr) with a constant expression. The form using an expression is necessary when implementing a generic data structure: with the expression it can be determined whether any of the type dependent operations may throw an exception.

For example, std::swap() is declared something like this:

template <typename T>
void swap(T& o1, T& o2) noexcept(noexcept(T(std::move(o1)) &&
noexcept(o1 = std::move(o2)));

Based on noexcept(swap(a, b)) the library can then choose differently efficient implementations of certain operations: if it can just swap() without risking an exception it may temporarily violate invariants and recover them later. If an exception might be thrown the library may instead need to copy objects rather than moving them around.

It is unlikely that the standard C++ library implementation will depend on many operations to be noexcept(true). The probably the operations it will check are mainly those involved in moving objects around, i.e.:

  1. The destructor of a class (note that destructors are by default noexcept(true) even without any declaration; if you have destructor which may throw, you need to declare it as such, e.g.: T::~T() noexcept(false)).
  2. The move operators, i.e. move construction (T::T(T&&)) and move assignment (T::operator=(T&&)).
  3. The type's swap() operations (swap(T&, T&) and possibly the member version T::swap(T&)).

If any of these operations deviates from the default you should declare it correspondingly to get the most efficient implementation. The generated versions of these operations declare whether they are throwing exceptions based on the respective operations used for members and bases.

Although I can imagine that some operations may be added in the future or by some specific libraries, I would probably not declaration operations as noexcept for now. If other functions emerge which make a difference being noexcept they can be declared (and possible changed as necessary) in the future.

Should I use noexcept for getters always?

noexcept is a promise that is very hard to take back. For example, you could later do something as simple as change the return type to std::string (for whatever reason), but because that needs to allocate a copy of the string, it can throw.

So the standard went the way of "add noexcept only when it's necessary or highly beneficial", and I think that's a good rule to follow. The question you need to ask yourself is, will the callers of this method need it to not throw?

Shall we use noexcept everywhere in this case?

I think that it could be useful in your setup. The reason is that standard library containers and algorithms can use more optimised implementations of certain operations if these operations are noexcept().

How to know when a function will throw and when to use noexcept

but what are some other expressions/operators that can throw?

Potentially-throwing expressions are defined as (according to cppreference)

An expression e is potentially-throwing if:

  • e is a function call to a potentially-throwing function or pointer to function
  • e makes an implicit call to a potentially-throwing function (such as an overloaded operator, an allocation function in a new-expression, a constructor for a function argument, or a destructor if e is a full-expression)
  • e is a throw-expression
  • e is a dynamic_cast that casts a polymorphic reference type
  • e is a typeid expression applied to a dereferenced pointer to a polymorphic type
  • e has an immediate subexpression that is potentially-throwing

Also, any expression that has undefined behaviour.

A function that is not declared noexcept is potentially-throwing as far as the language is concerned, even if it might never throw.

Is there a way to explicitly determine if it will?

In general no, you cannot determine whether an expression will throw - at least not in polynomial time assuming P ≠ NP.

However, you can determine whether an expression is potentially-throwing using the noexcept-expression:

void foo() noexcept;
void bar() {
// nothing that might throw
}

std::cout << noexcept(1+1); // prints 1
std::cout << noexcept(foo()) // prints 1
std::cout << noexcept(bar()) // prints 0
std::cout << noexcept(new char); // prints 0
std::cout << noexcept(throw 1); // prints 0

Is noexcept useless when not throwing is zero-cost?

Is the noexcept specifier useless if your implementation has a zero-cost (if nothing is thrown) exception model?

No, noexcept would be useful even if exceptions had no performance impact at all.

One example is that noexcept can signal which algorithm can be used. For example algorithms that use std::move_if_noexcept or many of the standard type_traits could behave differently depending on the presence of noexcept.

This can have a significant impact for common features like std::vector which will be much slower if you elements' move constructor isn't noexcept. std::vector will copy all elements when reallocating instead of moving them if the move constructor is not noexcept to preserve the strong exception guarantee.

Should I declare a method noexcept if it never throws when used correctly?

This is not a simple question. In the general case, in C++ you would document your contract stating that the behavior is undefined unless the container is non-empty. The implication is that a call out of context can cause any possible behavior. The use of noexcept in such interfaces then limits what the range of any possible behavior is: it is any possible behavior that does not involve throwing an exception across the boundary.

Why is this important? Where I work we use BSL which is roughly an implementation of an extended C++03 standard library. Part of the library includes utilities for defensive programming and testing. Rather than using assert, the library uses its own flavor of assertion BSLS_ASSERT macros to verify contract violations. The library is built such that user code can control what happens when an assertion is triggered, and that is effectively used in test drivers to verify not only positive behavior (the component does what it should) and negative behavior (it does not do what it shouldn't) but also that it has the appropriate checks for contract violations. For that, an assert handler that throws a particular form of exception is used, and the test driver can then call out of contract and verify that the component is checking the behavior…

Long winded story, the point is that if that if the functions with narrow contracts (can be called out of contract) are marked as noexcept because the implementation should never throw (calling front() on an container), then when called out of contract it cannot throw, and the above mechanism cannot be used to verify that the component will detect contract violations.

This was part of the reason for a late revision of the C++11 standard (just before approval) to remove noexcept from all functions with a narrow contract. You can read more in this proposal



Related Topics



Leave a reply



Submit