In C++, the noexcept
specifier is used to indicate that a function does not throw exceptions. When applied to move constructors and move assignment operators, it has a special meaning and can enable significant optimizations.
Consider a generic function that takes an object by value:
template <typename T>
void Function(T obj) {
// ...
}
When Function
is called with an rvalue (such as a temporary), the compiler has a choice: it can either move from the rvalue or copy from it. If the move constructor of T
is noexcept
, the compiler knows that moving is guaranteed to succeed and will prefer to move. If the move constructor is not noexcept
, the compiler will typically choose to copy to avoid the potential for an exception during the move.
Here's an example:
#include <iostream>
class Resource {
public:
// Default constructor
Resource() {}
// Copy constructor
Resource(const Resource& R) {}
// Copy assignment
Resource& operator=(const Resource& R) {
return *this;
}
// Move constructor
Resource(Resource&& R) noexcept {}
// Move assignment
Resource& operator=(Resource&& R) noexcept {
std::cout << "Using Move Assignment";
return *this;
}
};
Resource CreateResource() {
Resource Temp;
return Temp;
}
int main() {
Resource A;
A = CreateResource();
}
Using Move Assignment
In this case, because Resource
's move constructor is marked noexcept
, the compiler knows it's safe to move from the temporary returned by CreateResource()
. If the move constructor were not noexcept
, the compiler would likely choose to copy instead, which could be less efficient.
Marking move operations as noexcept
is particularly important for types that are used in standard library containers (like std::vector
), because the standard library relies on move operations being noexcept
to enable certain optimizations.
In general, if your move operations don't throw exceptions (which they usually shouldn't), mark them noexcept
to enable these optimizations. But be careful - if you mark a function noexcept
and it does throw, the program will terminate immediately.
Answers to questions are automatically generated and may not have been reviewed.
Learn how we can improve the performance of our types using move constructors, move assignment operators and std::move()