/ | ||||
(C++11) | ||||
(C++11) |
(C++11) | ||||
(C++20) | ||||
(C++20) |
(C++11) | ||||
expression |
pointer |
specifier | ||||
specifier (C++11) | ||||
specifier (C++11) |
(C++11) | ||||
(C++11) |
(C++11) | ||||
(C++11) |
General | ||||
(C++11) | ||||
(C++20) | ||||
(C++26) | ||||
(C++11) | ||||
(C++11) |
-expression | ||||
-expression | ||||
-expression |
(C++11) | ||||
(C++11) | ||||
(C++17) | ||||
(C++20) |
block | ||||
Exception specification | ||||
specification (C++11) | ||||
(until C++17*) | ||||
operator (C++11) |
Specifies whether a function could throw exceptions.
Syntax Explanation Notes Deprecates Keywords Example Defect reports See also |
(1) | |||||||||
expression | (2) | ||||||||
(3) | (deprecated in C++17) (removed in C++20) | ||||||||
expression | - |
The noexcept-specification is not a part of the function type (just like ) and can only appear as a part of a or a top-level when declaring functions, variables, non-static data members of type function, pointer to function, reference to function, or pointer to member function, and also when declaring a parameter or a return type in one of those declarations that in turn happens to be a pointer or reference to function. It cannot appear in a or declaration. f() noexcept; // the function f() does not throw void (*fp)() noexcept(false); // fp points to a function that may throw void g(void pfa() noexcept); // g takes a pointer to function that doesn't throw // typedef int (*pf)() noexcept; // error | (until C++17) |
The noexcept-specification is a part of the function type and may appear as part of any . | (since C++17) |
Every function in C++ is either non-throwing or potentially throwing :
(until C++17) |
that are defaulted on their first declaration unless the invocation of any comparison operator in the implicit definition is (see below) | (since C++20) |
Explicit instantiations may use the noexcept specifier, but it is not required. If used, the exception specification must be the same as for all other declarations. A diagnostic is required only if the exception specifications are not the same within a single translation unit.
Functions differing only in their exception specification cannot be overloaded (just like the return type, exception specification is part of function type, but not part of the function signature) (since C++17) .
Pointers (including pointers to member function) to non-throwing functions can be assigned to or used to initialize (until C++17) are implicitly convertible to (since C++17) pointers to potentially-throwing functions, but not the other way around.
If a virtual function is non-throwing, all declarations, including the definition, of every overrider must be non-throwing as well, unless the overrider is defined as deleted:
Non-throwing functions are permitted to call potentially-throwing functions. Whenever an exception is thrown and the search for a handler encounters the outermost block of a non-throwing function, the function std::terminate is called:
The exception specification of a function template specialization is not instantiated along with the function declaration; it is instantiated only when needed (as defined below).
The exception-specification of an implicitly-declared special member function is also evaluated only when needed (in particular, implicit declaration of a member function of a derived class does not require the exception-specification of a base member function to be instantiated).
When the noexcept-specification of a function template specialization is needed , but hasn't yet been instantiated, the dependent names are looked up and any templates used in the expression are instantiated as if for the declaration of the specialization.
A noexcept-specification of a function is considered to be needed in the following contexts:
Formal definition of potentially-throwing expression (used to determine the default exception specification of destructors, constructors, and assignment operators as described above):
An expression e is potentially-throwing if:
One of the uses of the constant expression is (along with the noexcept operator ) to define function templates that declare noexcept for some types but not others.
Note that a noexcept specification on a function is not a compile-time check; it 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 pre-C++17 throw ( ) , noexcept will not call std::unexpected , may or may not unwind the stack, and will call std::terminate , which potentially allows the compiler to implement noexcept without the runtime overhead of throw ( ) . As of C++17, throw ( ) is redefined to be an exact equivalent of noexcept ( true ) .
Feature-test macro | Value | Std | Feature |
---|---|---|---|
201510L | (C++17) | Make exception specifications be part of the type system |
noexcept , throw (since C++17) (until C++20)
[ edit ] defect reports.
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
DR | Applied to | Behavior as published | Correct behavior |
---|---|---|---|
C++11 | an exception specification might be eagerly instantiated | it is only instantiated only if needed | |
C++11 | a ( following noexcept might start an initializer | it can only be a part of noexcept specification | |
C++11 | only the expression before conversion is required to be constant | the conversion must also be valid in a constant expression |
operator(C++11) | determines if an expression throws any exceptions |
(until C++17) | specifies what exceptions are thrown by a function (deprecated in C++11) |
expression | signals an error and transfers control to error handler |
obtains an rvalue reference if the move constructor does not throw (function template) |
Clang-tidy - performance-noexcept-move-constructor.
« performance-noexcept-destructor :: Contents :: performance-noexcept-swap »
The check flags user-defined move constructors and assignment operators not marked with noexcept or marked with noexcept(expr) where expr evaluates to false (but is not a false literal itself).
Move constructors of all the types used with STL containers, for example, need to be declared noexcept . Otherwise STL will choose copy constructors instead. The same is valid for move assignment operations.
Search code, repositories, users, issues, pull requests..., provide feedback.
We read every piece of feedback, and take your input very seriously.
Use saved searches to filter your results more quickly.
To see all available qualifiers, see our documentation .
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement . We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
According to I think this is particularly important for Variant itself that sometimes is a vector of Variant |
The text was updated successfully, but these errors were encountered: |
This should land in the next release. Thanks for the feature request. |
Sorry, something went wrong.
No branches or pull requests
Discussions, articles and news about the C++ programming language or programming in C++.
A situation came up recently where we realised that the move assignment operator for std::function is not noexcept http://eel.is/c++draft/func.wrap.func.con#19 , despite the fact that the move constructor is (further above on that link). The std::swap for std::function is noexcept too.
I managed to find proposal P0771 that looks to change this but I'm not sure how to find the status of the proposal. That proposal suggests changing both the move construct and the move assignment operator, so presumably the move constructor was not initially noexcept .
So, I guess the question is, is this done for a reason? It seems unusual that there would be a discrepancy between the constructor and assignment operator.
By continuing, you agree to our User Agreement and acknowledge that you understand the Privacy Policy .
You’ve set up two-factor authentication for this account.
Create your username and password.
Reddit is anonymous, so your username is what you’ll go by here. Choose wisely—because once you get a name, you can’t change it.
Enter your email address or username and we’ll send you a link to reset your password
An email with a link to reset your password was sent to the email address associated with your account
If you skim the remaining rules to error handling, you often read the word noexcept . Before I write about the rules for error handling, I will write about the noexcept specifier and the noexcept operator in this post.
noexcept exists in two forms since C++11: as a specifier and as an operator. The C++ core guidelines use the specifier.
By declaring a function, a method, or a lambda function as noexcept , you specify that these do not throw an exception, and if they throw, you do not care and let the program crash. For simplicity reasons, I will write about function but also mean methods and function templates. There are various ways to express your intention:
The noexcept specification is equivalent to the noexcept(true) specification. throw( ) is equivalent to noexcept(tru e) but was deprecated with C++11 and will be removed with C++20. In contrast, noexcept(false) means that the function may throw an exception. The noexcept specification is part of the function type but can not be used for function overloading.
There are two good reasons for using noexcept : First, an exception specifier documents the function’s behavior. If a function is specified as noexcept , it can be safely used in a non-throwing function. Second, it is an optimization opportunity for the compiler. noexcept may not call std::unexpected and may not unwind the stack. The initialization of a container may cheaply move the elements into the container if the move constructor is declared as noexcept. If not declared as noexcept, the elements may be expensive copied into the container.
Each function in C++ is either non-throwing or potentially throwing. Potentially throwing means:
There is an exception to rule 2, that functions are potentially throwing if they have no noexcept specification. These exceptions include the following six special member functions. They are implicitly non-throwing.
Be part of my mentoring programs:
Do you want to stay informed: Subscribe.
This special six member such as the destructor, can only be non-throwing if all destructors of the attributes and the bases-classes are non-throwing. Of course, the corresponding statement will hold for the five other special member functions.
What happens when you throw an exception in a function declared non-throwing? In this case, std::terminate is called. std::terminate calls the currently installed std::terminate_handler which calls std::abort by default.The result is an abnormal program termination.
For completeness, is want to present noexcept as operator.
The noexcept operator checks at compile-time if an expression does not throw an exception. The noexcept operator does not evaluate the expression. It can be used in a noexcept specifier of a function template to declare that the function may throw exceptions depending on the current type.
To make my description clear, here is a simple example of a function template that copies its return value.
Of course, the most exciting line in this example is line (1). In particular, the expression noexcept(noexcept(T(src)). The inner noexcept ist the noexcept operator, and the outer is the noexcept specifier. The expression noexcept(T(src)) checks if the copy constructor is non-throwing . This is the case for the class Noexcept (2) but not for the class NonNoexcept (3) b ecause of the copy constructor of std::vector that may throw . Consequently, expression (4) returns true , and expression (5) returns false.
Maybe you know about it. You can check at compile time with the help of the type traits library if a type T has a non-throwing copy constructor: std::is_nothrow_copy_constructible::value . Based on this predicate, you can use instead of the noexcept operator the predicate from the type traits library:
I don’t know which version of copy do you prefer. I prefer the type traits version because it is more expressive.
The following rule is about the noexcept specifier.
The title of this rule may be a little bit confusing. It says that you should declare a function as noexcept, if
It’s not a good idea to throw an exception if you are the direct owner of an object.
Here is an example to direct ownership from the guidelines:
If the throw is fired, the memory is lost, and you leak. The simple solution is to remove the ownership and make the C++ runtime to the direct owner of the object. Just create a local object or at least a guard as a local object. And you know the C++ runtime takes care of local objects. Here are three variations of this idea.
p1 is locally created, but p2 and p3 are kinds of guards for the objects. The std::vector uses the heap to manage its data. Additionally, with all three variations, you eliminate the delete call.
Here is a compilation of my standard seminars. These seminars are only meant to give you a first orientation.
Modernes C++ Mentoring,
Leave a reply cancel reply.
Your email address will not be published. Required fields are marked *
Find centralized, trusted content and collaborate around the technologies you use most.
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Get early access and see previews of new features.
As far as I know, if move constructor/assignment operator are either implicitly generated or explicitly defaulted by user (1) , the compiler will decide whether these special member functions should be noexcept or not depending on whether all the members of a class provide noexcept guarantees for move operations. But what if I want to use default move special members and force them to be noexcept regardless of the underlying members exception guarantees for move operations? Is there any difference for the compiler between (1) and (2) declarations?
Ok, I found the answer in Nico's Josuttis book "C++ Move Semantics - The Complete Guide":
When you have a defaulted special member function you can explicitly specify a different noexcept guarantee than the generated one. For example: class C { ... public: C(const C&) noexcept = default; // guarantees not to throw (OK since C++20) C(C&&) noexcept(false) = default; // specifies that it might throw (OK since C++20) ... }; Before C++20, if the generated and specified noexcept condition contradict, the defined function was deleted.
I asked this question because I want STL algorithms to always apply move semantics to my classes regardless of their members' exception guarantees, and I am ready to deal with std::abort if something goes wrong. But it seems that prior to C++ 20 the only way to force noexcept guarantees on move special member functions was to explicitly define them, even if you don't need your own implementation. It turns out C++20 solved this by allowing us to specify noexcept guarantees for defaulted special member functions. Of course, as in case with any other noexcept function, if any of the members of a class throws during a move operation, std::abort will be called if move constructor/assignment operator are declared noexcept for that class, as it was kindly pointed out by @MichaëlRoy in the comments section.
Reminder: Answers generated by artificial intelligence tools are not allowed on Stack Overflow. Learn more
Post as a guest.
Required, but never shown
By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy .
COMMENTS
@Klaus, for the OP's examples the compiler can already see that those operations don't throw, adding noexcept tells it nothing. In general, if the function definition is visible and suitable for inlining then the compiler has all the information it needs to make that decision anyway, without noexcept.Any advantages in codegen (such as not needing to generate unwinding info) applies to all ...
It seems that std::vector in particular is picky about whether or not you declare your move constructors with noexcept. If you do, then std::vector will use them. If you don't then std::vector will resort to using your copy constructor instead. At least in some cases. Notably whenever it reshuffles items internally, after an internal array resize.
Move constructors and move assignment should be marked as noexcept. This tells the compiler that these functions will not throw exceptions. We introduce noexcept in lesson 27.9 -- Exception specifications and noexcept and discuss why move constructors and move assignment are marked as noexcept in lesson 27.10 -- std::move_if_noexcept.
The move assignment operator is called whenever it is selected by overload resolution, e.g. when an object appears on the left-hand side of an assignment expression, where the right-hand side is an rvalue of the same or implicitly convertible type.. Move assignment operators typically "steal" the resources held by the argument (e.g. pointers to dynamically-allocated objects, file descriptors ...
This topic describes how to write a move constructor and a move assignment operator for a C++ class. A move constructor enables the resources owned by an rvalue object to be moved into an lvalue without copying. For more information about move semantics, see Rvalue Reference Declarator: &&. This topic builds upon the following C++ class ...
Triviality of eligible move constructors determines whether the class is an implicit-lifetime type, and whether the class is a trivially copyable type. [] NoteTo make the strong exception guarantee possible, user-defined move constructors should not throw exceptions. For example, std::vector relies on std::move_if_noexcept to choose between move and copy when the elements need to be relocated.
Friendly reminder to mark your move constructors noexcept. by AndyG. From the article: Since C++11 we have had the noexcept keyword, which is a promise that the function will not throw an exception (and if it does, go straight to std::terminate, do not pass go). noexcept is nice for two reasons: The compiler can optimize a little better because ...
Warning. If a type has both potentially throwing move semantics and deleted copy semantics (the copy constructor and copy assignment operator are unavailable), then std::move_if_noexcept will waive the strong guarantee and invoke move semantics. This conditional waiving of the strong guarantee is ubiquitous in the standard library container classes, since they use std::move_if_noexcept often.
In C+, the move assignment operator is used to transfer the ownership of the resources from one object to another when the object is assigned some rvalue references or using std::move. It allows efficient memory manipulation by avoiding unnecessary copies of the objects. In this article, we will learn how to implement a move assignment operator in
The move assignment operator was added in C++ 11 to further strengthen the move semantics in C++. It is like a copy assignment operator but instead of copying the data, this moves the ownership of the given data to the destination object without making any additional copies. The source object is left in a valid but unspecified state.
C++中为什么move construct需要加noexcept. C++ 11中增加了名为移动构造函数的构造函数类型。通过使用移动构造函数,我们可以在进行对象复制时直接"窃取"拷贝对象所保有的一些资源,比如已经在原对象中分配的堆内存,文件描述符,IO流等。通常我们在声明移动构造函数时,都会使用 noexcept 关键字来 ...
The noexcept-specification is a part of the function type and may appear as part of any function declarator . (since C++17) Every function in C++ is either non-throwing or potentially throwing : potentially-throwing functions are: functions declared with a non-empty dynamic exception specification. (until C++17)
Move constructors of all the types used with STL containers, for example, need to be declared noexcept. Otherwise STL will choose copy constructors instead. The same is valid for move assignment operations. «
Just use the move-and-swap idiom. T& operator=(T t) noexcept { //swap each member with t return *this; } Pros: Serves both as move-assignment and copy-assignment, if there is a copy constructor. Reuse the code from the move-constructor Can be marked noexcept (provided that the swap is noexcept, that is in 99% of the cases).
Move constructors and assignment operators should be marked as noexcept #24. Closed tsdgeos opened this issue Sep 30, 2019 · 1 comment ... need to be declared noexcept. Otherwise STL will choose copy constructors instead. The same is valid for move assignment operations. I think this is particularly important for Variant itself that sometimes ...
operator behaves as a copy assignment under certain conditions, making the noexcept guarantee impossible. In general, algorithmic efficiency can be improved if the move constructor and swap functions are noexcept, as they would be with this proposal. A much smaller set of algorithms benefit from a noexcept move-assignment operator.
The std::swap for std::function is noexcept too. I managed to find proposal P0771 that looks to change this but I'm not sure how to find the status of the proposal. That proposal suggests changing both the move construct and the move assignment operator, so presumably the move constructor was not initially noexcept.
The move assignment operator in container classes is defined to be noexcept because many containers are designed to implement the strong exception safety guarantee. Containers implement the strong exception safety guarantee because back before there were move assignment operators, the container had to be copied.
In particular, the expression noexcept (noexcept (T (src)). The inner noexcept ist the noexcept operator, and the outer is the noexcept specifier. The expression noexcept (T (src)) checks if the copy constructor is non-throwing. This is the case for the class Noexcept (2) but not for the class NonNoexcept (3) b ecause of the copy constructor of ...
Ok, I found the answer in Nico's Josuttis book "C++ Move Semantics - The Complete Guide": When you have a defaulted special member function you can explicitly specify a different noexcept guarantee than the generated one.