英文:
Move operation even if Destructor is defined
问题
我阅读了这个内容:
> N3337 [class.copy]/9:如果类X的定义没有明确声明移动构造函数,则仅当以下条件满足时,将隐式声明为默认构造函数:
>
> X没有用户声明的复制构造函数,
> X没有用户声明的复制赋值运算符,
> X没有用户声明的移动赋值运算符,
> X没有用户声明的析构函数,并且
> 移动构造函数不会被隐式定义为已删除。
> 声明析构函数并将其定义为默认构造函数视为用户声明。
这里:https://stackoverflow.com/questions/33957037/does-a-default-virtual-destructor-prevent-compiler-generated-move-operations
然而,这段代码:
struct A1 { virtual ~A1() {}; };
struct B1 : public A1 {
~B1() override {}; };
struct A2 { virtual ~A2() = default; };
struct B2 : public A2 {
~B2() override = default; };
struct A_NO_VIRTUAL {
~A_NO_VIRTUAL() {}; };
struct B_NO_VIRTUAL : public A_NO_VIRTUAL {
~B_NO_VIRTUAL() {}; };
int main() { std::cout << std::is_nothrow_move_constructible_v<B1> << std::is_nothrow_move_constructible_v<B2> << std::is_nothrow_move_constructible_v<B_NO_VIRTUAL> << std::endl; }
输出:
111
见:http://coliru.stacked-crooked.com/a/5c53057a1a4ce3f4
预期:
000
为什么会这样?
英文:
I read this:
> N3337 [class.copy]/9: If the definition of a class X does not explicitly declare a move constructor, one will be implicitly declared as defaulted if and only if
>
> X does not have a user-declared copy constructor,
> X does not have a user-declared copy assignment operator,
> X does not have a user-declared move assignment operator,
> X does not have a user-declared destructor, and
> the move constructor would not be implicitly defined as deleted.
> Declaring the destructor and defining it as default counts as user-declared.
However, this code:
struct A1 { virtual ~A1() {}; };
struct B1 : public A1 {
~B1() override {}; };
struct A2 { virtual ~A2() = default; };
struct B2 : public A2 {
~B2() override = default; };
struct A_NO_VIRTUAL {
~A_NO_VIRTUAL() {}; };
struct B_NO_VIRTUAL : public A_NO_VIRTUAL {
~B_NO_VIRTUAL() {}; };
int main() { std::cout << std::is_nothrow_move_constructible_v<B1> << std::is_nothrow_move_constructible_v<B2> << std::is_nothrow_move_constructible_v<B_NO_VIRTUAL> << std::endl; }
prints:
111
See: http://coliru.stacked-crooked.com/a/5c53057a1a4ce3f4
expected:
000
Why is that?
答案1
得分: 5
is_move_constructible
大致检查 MyClass x(std::move(y));
是否有效。如果 MyClass
没有移动构造函数,但有拷贝构造函数,这也可以是有效的,拷贝构造函数会在移动构造函数的位置默默地使用。
只声明析构函数会移除移动操作,但保留拷贝操作(后者已被弃用)。
要正确测试这一点,请向您的类添加一个成员变量,并记录成员的拷贝和移动构造函数的调用。
英文:
is_move_constructible
roughly checks whether MyClass x(std::move(y));
is valid. It can be valid if MyClass
doesn't have a move constructor, but does have a copy constructor, which is going to be silently used in place of the move constructor.
Declaring a destructor only removes the move operations, but keeps the copy ones (the latter is deprecated).
To test this properly, add a member variable to your class, and log the calls to the member's copy and move constructors.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论