在Stack Overflow post 中,我有这样的评论:
在C++11中,你实际上会想要做virtual ~A() = default;
,否则你会丢失隐式的
构造器。
virtual ~A() = default;
是用来做什么的?为什么隐式移动构造函数在virtual ~A() {}
中丢失了
发布于 2013-06-21 03:26:19
评论是不正确的。
两者:
virtual ~A() = default;
和
virtual ~A() {}
用户是否声明为。如果析构函数是用户声明的,则禁止隐式移动成员。
dcl.fct.def.default/p4讨论用户声明和用户提供的特殊成员:
如果特殊成员函数是用户声明的,并且在第一次声明时没有显式地默认或删除,则该函数是用户提供的。
发布于 2013-06-21 03:33:18
在这篇文章https://stackoverflow.com/a/17204598/260127中,我有这样的评论:
在C++11中,你实际上想要做virtual ~A() = default;
,否则你会丢失隐式的移动构造器。
注释不正确。
即使是default
ed,该析构函数也是“用户声明的”(尽管请注意,它并非也是“用户提供的”)。
#include <iostream>
struct Helper
{
Helper() {}
Helper(const Helper& src) { std::cout << "copy\n"; }
Helper(Helper&& src) { std::cout << "move\n"; }
};
struct A
{
virtual ~A() {}
Helper h;
};
struct B
{
virtual ~B() = default;
Helper h;
};
struct C
{
Helper h;
};
int main()
{
{
A x;
A y(std::move(x)); // outputs "copy", because no move possible
}
{
B x;
B y(std::move(x)); // outputs "copy", because still no move possible
}
{
C x;
C y(std::move(x)); // outputs "move", because no user-declared dtor
}
}
复制
复制
move
所以你并没有“丢失”任何东西--一开始就没有移动功能!
以下是在这两种情况下都禁止隐式移动构造函数的标准段落:
[C++11: 12.8/9]:
如果类X
的定义没有显式声明移动构造函数,则仅当且仅当
X
没有用户声明的复制构造函数,X
没有用户声明的复制赋值运算符,X
没有用户声明的移动赋值运算符,X
没有用户声明的析构函数,并且Bootnote
如果该标准的未来版本真正列出了“用户声明”等术语的确切含义,那也不会有什么坏处。至少,这是这样的:
[C++11: 8.4.2/4]:
..如果特殊成员函数是用户声明的,并且在第一次声明时没有显式地默认或删除,则该函数是用户提供的。。。
在这里,人们可以通过暗示来假设这种区别。
发布于 2013-06-21 03:05:46
这种评论是错误的。
不是提供你自己的移动构造函数,如果你希望编译器提供一个,其中一个要求是它希望析构函数也是由它提供的,即一个简单的析构函数。然而,当前的标准对何时可以提供隐式实现是相当严格的-接受用户如何给出析构函数。用户声明的任何内容都被认为是用户在自己手中处理问题,因此不仅如此
~A() { … }
但也有这个
~A() = default;
使编译器不提供隐式析构函数。第一个是定义,因此也是一个声明;第二个只是一个声明。在这两种情况下,析构函数都是用户声明的,因此禁止编译器提供隐式移动构造函数。
我猜这个要求背后的基本原理是,在移动过程中,对象的资源被移动到另一个对象,使原始对象处于动态存储中没有资源的状态;但是如果你的类没有任何这样的资源,那么它可以被简单地移动,销毁,等等。当你声明一个非平凡的析构函数时,它对编译器来说是一个提示,你在类中管理的资源不是微不足道的,你必须提供非平凡的移动,所以编译器不提供一个。
https://stackoverflow.com/questions/17221668
复制相似问题