Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

c++11

noexcept

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?

like image 789
Ankit Acharya Avatar asked Oct 19 '15 08:10

Ankit Acharya


People also ask

What is Noexcept in C?

The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.

Why should I use Noexcept?

There are two good reasons for the use of noexcept: First, an exception specifier documents the behaviour of the function. If a function is specified as noexcept, it can be safely used in a non-throwing function. Second, it is an optimisation opportunity for the compiler.

Should I add Noexcept?

Templates like move_if_noexcept will detect if the move constructor is defined with noexcept and will return a const& instead of a && of the type if it is not. It's a way of saying to move if it is very safe to do so. In general, you should use noexcept when you think it will actually be useful to do so.

Does Noexcept make code faster?

That noexcept keyword is tricky, but just know that if you use it, your coding world will spin faster.

What is noexcept in C++ with example?

noexcept operator. (since C++11) The noexcept operator performs a compile-time check that returns true if an expression is declared to not throw any exceptions. It can be used within a function template's noexcept specifier to declare that the function will throw exceptions for some types but not others.

Should I add noexcept to my function's interface?

I disagree. noexcept is part of the function's interface; you should not add it just because your current implementation happens not to throw. I am not sure about the right answer to this question, but I am quite confident that how your function happens to behave today has nothing to do with it... As I keep repeating these days: semantics first.

What happens when a function throws a noexcept exception?

If a function marked noexcept does throw, then std::terminate is called. immediately benefiting from noexcept even when dependencies do not use it already (backward compatibility) allowing the specification of noexcept when calling functions that may theoretically throw, but are not expected to for the given arguments

When should I use the noexcept keyword in practice?

The noexcept keyword can be appropriately applied to many function signatures, but I am unsure as to when I should consider using it in practice. Based on what I have read so far, the last-minute addition of noexcept seems to address some important issues that arise when move constructors throw.


3 Answers

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
}
like image 64
Validus Oculus Avatar answered Oct 20 '22 12:10

Validus Oculus


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

like image 16
DevInd Avatar answered Oct 20 '22 11:10

DevInd


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.

like image 8
Tommy Andersen Avatar answered Oct 20 '22 10:10

Tommy Andersen