33

I am unable to understand the use & purpose of the noexcept keyword in C++11/14. I understand that it is a signature for a function that does not emit exceptions. But does it really work?

Look at this code below :

#include <iostream> #include <bits/stdc++.h> using namespace std; void seev (vector<int> &v) noexcept; void seev (vector<int> &v) noexcept { for (int i=0;i<10;++i) { cout<<v.at(i)<<' '; } } int main() { vector<int> v {1,2,3,4,5}; seev(v); return 0; } 

The above code will surely throw an out_of_range exception. So the use of noexcept here is useless, or is it?

My queries are :

  1. How does noexcept work?

  2. How is it used?

  3. What throw() wasn't able to do that noexcept could?

2

3 Answers 3

24

From cppreference:

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

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 } 
Sign up to request clarification or add additional context in comments.

Comments

19

I'm posting 2 pieces of code to explain your problem:

Code 1:

#include <iostream> using namespace std; void foo() noexcept // see the noexcept specifier { throw 42; } int main() { try { foo(); } catch(...) { cerr<<"exception caught\n"; } return 0; } 

Here the output will be:

terminate called after throwing an instance of 'int' This application has requested the Runtime to terminate it in an unusual way. Please contact the application's support team for more information. 

If I remove the noexceptthen:

Code 2:

#include <iostream> using namespace std; void foo() // noexcept is eliminated { throw 42; } int main() { try { foo(); } catch(...) { cerr<<"exception caught\n"; } return 0; } 

Output will be:

exception caught 

Because foo was signed as noexcept, hence terminate was called.

Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, and move-assignment operators are all noexcept(true) by default, unless they are required to call a function that is noexcept(false), in which case these functions are noexcept(false).

You can also write lines like:

cout << boolalpha << noexcept(foo); // here noexcept acts as // an operator instead of a specifier 

The above line will check if foo will throw an exception or not. If it would throw then the return value will be true else false.

You can read more about these in this: http://scottmeyers.blogspot.dk/2014/03/declare-functions-noexcept-whenever.html

1 Comment

I think it's strong to claim the first result "will be" - that's very much an implementation-defined error message.
10

noexcept indicates that a function is intended not to to throw an exception, a guarantee you as a developer provides, that is not enforced by the compiler. So using it in a situation where your function calls functions that might throw exceptions that you do not catch yourself is bad.

The whole range of throw() specifiers were removed because the exception specifiers were less than optimal in C++, see: Difference between C++03 throw() specifier C++11 noexcept

noexcept has the advantage of not stating which exception is thrown, but rather whether an exception is thrown or not. It accepts a parameter which may be false if you expect the function to throw an exception.

The uses of this, can be in for instance an inherited class structure, where one super class wish to "enforce" to an inherited class, that a specific virtual function is not allowed to throw an exception. Further more the compiler may use the information for optimization.

noexcept is also an operator which can evaluate an expression and return whether or not that expression may thrown an exception or not, as per § 5.3.7.

5.3.7 noexcept operator [expr.unary.noexcept]

1 The noexcept operator determines whether the evaluation of its operand, which is an unevaluated operand (Clause 5), can throw an exception (15.1). noexcept-expression: noexcept ( expression )

2 The result of the noexcept operator is a constant of type bool and is an rvalue.

3 The result of the noexcept operator is false if in a potentially-evaluated context the expression would contain

— a potentially-evaluated call to a function, member function, function pointer, or member function pointer that does not have a non-throwing exception-specification (15.4), unless the call is a constant expression (5.19),
— a potentially-evaluated throw-expression (15.1),
— a potentially-evaluated dynamic_cast expression dynamic_cast(v), where T is a reference type, that requires a run-time check (5.2.7), or
— a potentially-evaluated typeid expression (5.2.8) applied to a glvalue expression whose type is a polymorphic class type (10.3).
Otherwise, the result is true.

I can't explain the possible optimizations as well as Scott Meyers: http://aristeia.com/EC++11-14/noexcept%202014-03-31.pdf from his blog post: Declare functions noexcept whenever possible?

The difference between unwinding the call stack and possibly unwinding it has a surprisingly large impact on code generation. In a noexcept function, optimizers need not keep the runtime stack in an unwindable state if an exception would propagate out of the function, nor must they ensure that objects in a noexcept function are destroyed in the inverse order of construction should an exception leave the function. The result is more opportunities for optimization, not only within the body of a noexcept function, but also at sites where the function is called. Such flexibility is present only for noexcept functions. Functions with “throw()” exception specifications lack it, as do functions with no exception specification at all.

7 Comments

then it seems useless
The compiler can perform optimizations if noexcept is present which otherwise would yield invalid code. This regards unwinding the stack in case of an exception.
it's not useless. Compilers can make advantage of noexcept and create mote optimized code. Generally code internally behaves in a different way, when there is or there is not noexcept word.
what kind of optimizations @TommyA ?
Hi @AnkitAcharya I knew I had read some post by Scott Meyers regarding it not long ago, I managed to find it, and have quoted him now :) should describe pretty well how it can affect optimization.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.