为什么 "=default" 析构函数与隐式声明的析构函数不同?
Why is a "=default" destructor different than the implicitly declared destructor?
所以我读了这篇文章:
默认构造函数和析构函数的"=default"与"{}"有何不同?
其中讨论了原因:
~Widget() = default;
与以下不同:
~Widget() {}
但是,"=default"情况与隐式声明的情况也不同。 从某种意义上说,=default 实际上并没有给你默认值,这有点奇怪。
请考虑以下程序:
class A
{
public:
A(std::string str)
{
m_str = str;
}
~A() = default;
A(A const& rhs)
{
printf("Got copiedn");
m_str = rhs.m_str;
}
A(A&& rhs)
{
printf("Got movedn");
m_str = std::move(rhs.m_str);
}
std::string m_str;
};
class B
{
public:
B(std::string test) : m_a(test)
{
}
~B() = default;
A m_a;
};
int main()
{
B b("hello world");
B b2(std::move(b));
return 0;
}
运行此程序将打印"已复制",除非您注释掉默认的~B((,在这种情况下,它将打印"已移动"。 这是为什么呢? 我认为"=default"非常令人困惑,考虑到这一点和隐式声明的析构函数应该产生"琐碎的析构函数"。
B
仅当
- 没有用户声明的复制构造函数;
- 没有用户声明的复制赋值运算符;
- 没有用户声明的移动分配运算符;
- 没有用户声明的析构函数;
现在,当您说~B() = default;
时,虽然您仍然获得默认析构函数,但它现在也被认为是用户声明的,因此不会有隐式定义的移动构造函数。
相关文章:
- 如果在C++中不需要构造函数或析构函数,是否有必要显式声明它?
- 为什么 "=default" 析构函数与隐式声明的析构函数不同?
- 我们什么时候应该在 C++ 中将析构函数声明为 =DELETE
- 析构函数在 lambda 捕获说明符中声明的类实例上运行两次
- 为什么在声明析构函数时必须声明 copy & move 构造函数?
- 当声明了虚拟析构函数但没有实现时会发生什么情况
- 析构函数删除在 main 中声明的动态数组
- 显式声明派生类中所需的析构函数
- 缺少析构函数声明
- 结构sqlite3的sqlite3c++正向声明导致析构函数中删除时出现无效指针错误
- 为什么简单析构函数在使用基指针声明时不删除派生对象
- C++自动生成带有用户声明析构函数的移动构造函数
- 不稳定的声明行为:Rational.h:25:错误:在"&"标记之前预期的构造函数、析构函数或类型转换
- C++ - 如果在循环中声明对象,是否在循环结束时调用其析构函数
- 如何在不中断移动和复制构造函数的情况下声明虚拟析构函数
- 声明析构函数虚拟就足够了吗?
- 为什么允许我声明一个带有已删除析构函数的对象
- 在类中声明并在 Main 中创建对象时隐式调用析构函数
- Forward声明和析构函数之间的关系
- 如果类至少包含一个虚拟函数,是否总是需要将析构函数声明为虚拟函数