Given the following code:
#include <iostream>
#include <vector>
#include <type_traits>
class Test {
public:
~Test() = default;
std::vector<int> m_vector;
};
int main() {
std::cout << std::is_nothrow_move_constructible_v<Test> << std::endl;
return 0;
}
It outputs 0
, meaning the Test
class can't be "nothrow moved". However, if I remove either ~Test()
or m_vector
then it returns 1
.
How to explain this please?
For reference, I'm using clang -7 with C 17.
CodePudding user response:
See [class.copy.ctor]/8:
If the definition of a class
X
does not explicitly declare a move constructor, a non-explicit one will be implicitly declared as defaulted if and only if [other conditions omitted, and]X
does not have a user-declared destructor.
Thus, the Test
class only has a copy constructor, not a move constructor. Any code that uses a Test
rvalue to initialize a new Test
object will use the copy constructor, which is not noexcept
because of the vector member. If the vector member is removed, the copy constructor of Test
will become trivial.
CodePudding user response:
When you define a user declared destructor, the class will not have an implicitly generated move constructor. Hence, moving will invoke copy constructor. The copy constructor of std::vector
is potentially throwing, hence the implicit copy constructor of Test
will also be potentially throwing.