In a modern C++ code compiler, there are many features that help you learn, master, and remember the various features and functions of the C++ language. One such feature of modern C++ is the move constructor that allows you to move the resources from one object to another without copying them. The C++11 standard provides an alternative to std::move
, which is std::move_if_noexcept
, to solve some problematic interactions between move constructors, templates, and certain standard library member functions. In this post, we explain what the move constructor is, what is std::move_if_noexcept
, and how we allow move constructors to throw [noexcept]
in C++.
First, let’s remind ourselves what is the move constructor in C++.
Table of Contents
What is a move constructor in C++?
The move constructor is a constructor that allows you to move the resources from one object to another object without copying them. The move constructor allows you to move the resources from an rvalue
object into to an lvalue
object. Here is the most common syntax for the move constructor in C++.
1 2 3 |
class_name ( class_name && ) |
and this is how you can create a move constructor in a class.
1 2 3 4 5 6 7 8 9 10 11 |
class Tx { public: Tx() = default; // Default Constructor Tx(Tx&& other) // A Typical Declaration of a Move Constructor { } } |
As shown above, if you have a move constructor, you should define a Constructor too, otherwise you will have “No matching constructor for initialization of class
” error in compilation. We can use move constructor with std::move
as in example below.
1 2 3 4 |
class Tx o1; class Tx o2 = std::move(o1); // Using Move Constructor |
Now, let’s see what is std::move_if_noexcept
in C++.
What is std::move_if_noexcept in C++?
The C++11 standard provides an alternative to std::move
, which is std::move_if_noexcept
, to solve some problematic interactions between move constructors, templates, and certain standard library member functions.
The move_if_noexcept
is an alternative to std:: move
in the standard library that combines move semantics with a strong exception guarantee. The std::move_if_noexcept
returns an rvalue reference to the argument unless copying is a better option than moving to provide at least a strong exception guarantee. In other words, the move_if_noexcept
is used to determine whether a move or a copy should be done. It returns an rvalue reference to the argument if its move constructor does not throw exceptions or if there is no copy constructor (move-only type), otherwise obtains an lvalue reference to its argument.
Here is the general header definition located in <utility> library
(since C++11),
1 2 3 4 5 6 7 8 |
template< class T > constexpr typename std::conditional< !std::is_nothrow_move_constructible<T>::value && std::is_copy_constructible<T>::value, const T&, T&& >::type move_if_noexcept( T& x ) noexcept; |
When we use std::move_if_noexcept(x)
, it grants permission to move x
unless it would throw (cause) an exception.
Is there a simple example of how to use std::move_if_noexcept in C++?
Here is a simple about move_if_noexcept
in C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
#include <utility> class Tx { }; int main() { Tx ox; Tx ox2 = std::move_if_noexcept(ox); } |
Here, note that a simple empty C++ class is perfectly equivalent to default implementations in a class (see Rule of Six).
Now, let’s see what is happening in a full example.
Is there a full example of how to use std::move_if_noexcept in C++?
Here is a full example of how to use move_if_noexcept
in C++.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
#include <iostream> #include <utility> class Tx { public: Tx() { } Tx(Tx&&) // move constructor that may throw { std::cout << "throwing Tx move constructor" << std::endl; } Tx(const Tx&) // copy constructor that may throw { std::cout << "throwing Tx copy constructor" << std::endl; } }; class Ty { public: Ty() { } Ty(Ty&&) noexcept // move constructor that will NOT throw { std::cout << "non-throwing Ty move constructor" << std::endl; } Ty(const Ty&) noexcept // copy constructor that will NOT throw { std::cout << "non-throwing Ty copy constructor" << std::endl; } }; int main() { Tx ox; Ty oy; std::cout << "std::move" << std::endl; Tx obx = std::move(ox); Ty oby = std::move(oy); std::cout << std::endl; std::cout << "std::move_if_noexcept" << std::endl; Tx objx = std::move_if_noexcept(ox); Ty objy = std::move_if_noexcept(oy); std::cout << std::endl; system("pause"); return 0; } |
Here is the output of move
and move_if_noexcept
usage:
1 2 3 4 5 6 7 8 9 10 11 |
std::move throwing Tx move constructor non-throwing Ty move constructor std::move_if_noexcept throwing Tx copy constructor non-throwing Ty move constructor Press any key to continue . . . |
For more information on this feature, see Allowing move constructors to throw Proposal document.
C++ Builder is the easiest and fastest C and C++ IDE for building simple or professional applications on the Windows, MacOS, iOS & Android operating systems. It is also easy for beginners to learn with its wide range of samples, tutorials, help files, and LSP support for code. RAD Studio’s C++ Builder version comes with the award-winning VCL framework for high-performance native Windows apps and the powerful FireMonkey (FMX) framework for cross-platform UIs.
There is a free C++ Builder Community Edition for students, beginners, and startups; it can be downloaded from here. For professional developers, there are Professional, Architect, or Enterprise version.
Design. Code. Compile. Deploy.
Start Free Trial
Free C++Builder Community Edition