为什么我们需要使用virtual〜A()= default; 而不是虚拟〜A(){}在C + + 11?
在堆栈溢出后检查C ++ 11中的对象types ,我有评论:
在C ++ 11中,你实际上想要做
virtual ~A() = default;
否则,你将失去implict构造函数。
什么是virtual ~A() = default;
对于? 如何隐式地移动构造函数与virtual ~A() {}
?
评论是不正确的。
都:
virtual ~A() = default;
和
virtual ~A() {}
是用户声明的 。 如果析构函数是用户声明的,则隐式移动成员将被禁止。
[dcl.fct.def.default] / p4讨论用户声明和用户提供的特殊成员:
一个特殊的成员函数是用户提供的,如果它是用户声明的,并且没有显式默认或删除它的第一个声明。
在这篇文章https://stackoverflow.com/a/17204598/260127 ,我有评论:
在C ++ 11中,你实际上想要做
virtual ~A() = default;
否则,你将失去implict构造函数。
评论是不正确的。
即使default
编辑,该析构函数是“ 用户声明 ”(虽然注意,它也不是“ 用户提供 ”)。
#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 } }
现场演示 :
+ g ++ – 4.8 -std = c ++ 11 -O2 -Wall -pthread main.cpp
+ ./a.out
复制
复制
移动
所以你没有“丢失”任何东西 – 那里没有任何移动function!
下面是在这两种情况下禁止隐式移动构造函数的标准通道:
[C++11: 12.8/9]:
如果一个类X
的定义没有明确声明一个移动构造函数,当且仅当它被隐式声明为默认
X
没有用户声明的拷贝构造函数,X
没有用户声明的复制赋值操作符,X
没有用户声明的移动赋值操作符,X
没有用户声明的析构函数 ,并且- 移动构造函数不会被隐式定义为删除。
Bootnote
如果标准的未来版本实际上列出了诸如“用户声明”之类的术语的确切含义,则不会受到伤害。 至less有这样的:
[C++11: 8.4.2/4]:
[..]一个特殊的成员函数是用户提供的,如果它是用户声明的,并且没有明确地默认或删除它的第一个声明。 [..]
人们可以通过暗示假设这个区别。
那个评论是错误的。
如果你想让编译器提供一个,那么它的一个要求就是它期望析构函数也是由它提供的,也就是一个简单的析构函数,而不是提供你自己的移动构造函数。 然而,当前的标准在可以提供隐式实现的时候非常严格 – 接受用户给出析构函数的方式。 用户声明的任何东西都被认为是用户正在把事情掌握在自己手中,因此不仅如此
~A() { … }
也是这个
~A() = default;
使编译器不提供隐式的析构函数。 首先是一个定义,也就是一个声明。 第二只是一个声明。 在这两种情况下,析构函数都是用户声明的,因此禁止编译器提供隐式移动构造函数。
我想这个要求背后的基本原理是,在移动过程中,一个对象的资源被移动到另一个对象,使原来的对象处于没有dynamic存储资源的状态。 但如果你的类没有任何这样的资源,那么它可以被平凡地移动,销毁等等。当你声明一个不平凡的析构函数时,它是编译器的一个提示,你在类中pipe理的资源不是微不足道的你大多不得不提供非平凡的举动 ,所以编译器不提供一个。
- 当一些调用工作而另一些调用失败时,$ q.all()会发生什么?
- 没有体系结构来编译(ONLY_ACTIVE_ARCH = YES,活动arch = x86_64,VALID_ARCHS = armv7 armv7s)