移动操作,即使已定义析构函数。

huangapple go评论65阅读模式
英文:

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.

Here: https://stackoverflow.com/questions/33957037/does-a-default-virtual-destructor-prevent-compiler-generated-move-operations

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.

huangapple
  • 本文由 发表于 2023年6月8日 04:11:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76426798.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定