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 :
How does noexcept
work?
How is it used?
What throw()
wasn't able to do that noexcept
could?
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.
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.
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.
That noexcept keyword is tricky, but just know that if you use it, your coding world will spin faster.
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.
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.
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
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.
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
}
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 noexcept
then:
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With