28

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?

Harry
  • 193
  • 1
  • 12
Ankit Acharya
  • 2,833
  • 3
  • 18
  • 29
  • Possible duplicate of [When should I really use noexcept?](http://stackoverflow.com/questions/10787766/when-should-i-really-use-noexcept) – m.s. Oct 19 '15 at 08:53
  • 1
    Helpful information can be found [here](http://stackoverflow.com/questions/26079903/noexcept-stack-unwinding-and-performance) and especially in [this answer](http://stackoverflow.com/a/26080332/1969455). – Brandlingo Oct 19 '15 at 08:54

3 Answers3

21

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
}
Community
  • 1
  • 1
Validus Oculus
  • 2,756
  • 1
  • 25
  • 34
  • 1
    I have edited my answer and added a sample source code. I didn't write it but it is so easy to understand yet very instructive. I hope it will be useful for you. – Validus Oculus Oct 19 '15 at 09:06
16

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

underscore_d
  • 6,309
  • 3
  • 38
  • 64
DevInd
  • 1,645
  • 2
  • 11
  • 17
8

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.

Community
  • 1
  • 1
Tommy Andersen
  • 7,165
  • 1
  • 31
  • 50
  • then it seems useless – Anwesha Oct 19 '15 at 08:54
  • 1
    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. – Brandlingo Oct 19 '15 at 08:56
  • 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. – DawidPi Oct 19 '15 at 08:56
  • could you plz elaborate @DawidPi – Ankit Acharya Oct 19 '15 at 08:57
  • 1
    what kind of optimizations @TommyA ? – Ankit Acharya Oct 19 '15 at 09:02
  • 2
    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. – Tommy Andersen Oct 19 '15 at 09:19
  • @AnkitAcharya No, at a minimum it is a clear statement of intent by the developer to users about the API and what it guarantees, and beyond that it can also enable optimisations, in particular moving instead of copying where a `noexcept` move constructor exists. So it is far from useless. – underscore_d Oct 06 '18 at 10:26