C++11 virtual destructors and auto generation of move special functions(C++11 虚拟析构函数和移动特殊函数的自动生成)
问题描述
C++11 中自动生成特殊移动函数(构造函数和赋值运算符)的规则规定不能声明析构函数.逻辑大概是,如果你需要在破坏中做一些特殊的事情,那一步可能不安全.
The rules for auto generating special move functions (constructor and assignment operator) in C++11 specify that no destructor can be declared. The logic is presumably that, if you need to do something special in destruction, that a move may not be safe.
然而,为了在多态中正确调用析构函数,有必要将基类的析构函数声明为虚拟的(否则通过其基类的指针删除子类的实例将无法正确链接析构函数).
However, for proper destructor calls in polymorphism, it is necessary to declare a base classes' destructor as virtual (otherwise deleting an instance of a sub class through a pointer of its base class will not properly chain the destructor).
我假设,即使是空的析构函数也会阻止编译器自动生成特殊的移动函数.如:
I'm assuming, then, that even an empty destructor would prevent the compiler from automatically generating a special move functions. As in:
class Base {
virtual ~Base() { }
};
但是,您可以默认析构函数,如下所示:
You can, however, default the destructor, as in:
class Base {
virtual ~Base() = default;
}
那么问题 1:这会允许编译器自动生成特殊移动函数吗?
So question 1: Will this allow the compiler to auto generate special move functions?
然而,显式默认析构函数存在问题.至少在 GCC 4.8.2 的情况下,签名被隐式更改为 noexcept.如:
There is a problem with the explicit default destructor, however. In at least the case of GCC 4.8.2, the signature is implicitly changed to noexcept. As in:
class Base {
virtual ~Base() = default; // compiler changes to:
// virtual ~Base() noexcept;
}
虽然我在析构函数中使用 noexcept 没有问题,但这会破坏以下客户端"代码:
While I have no problem with noexcept in a destructor, this would break the following "client" code:
class Sub : public Base {
virtual ~Sub(); // this declaration is now "looser" because of no noexcept
}
所以问题 2 更重要:有没有办法允许在 C++11 中自动生成特殊的移动函数并允许适当的析构函数链接到子类(如上所述),所有这些都不会破坏子类(客户端") 代码?
So question 2 is more to the point: is there a way to allow auto generation of special move functions in C++11 and allow proper destructor chaining to sub classes (as described above), all without breaking subclass ("client") code?
推荐答案
不,默认的析构函数仍被视为用户定义的,因此它将阻止移动操作的生成.还要声明移动操作
default
-ed 以使编译器生成它们.
No, a defaulted destructor is still considered user defined, so it will prevent the generation of move operations. Also declare the move operations
default
-ed to make the compiler generate them.
您只需在基类中将移动操作声明为 default
-ed.在派生类中,析构函数不再是用户定义的(除非您明确说明),因此不会删除移动操作.
You need to only declare the move operations as default
-ed in the base class. In the derived class, the destructor won't be user defined anymore (unless you explicitly say so), so the move operations won't be deleted.
所以我要做的是:
class Base
{
virtual ~Base() = default;
Base(Base&&) = default;
Base& operator=(Base&&) = default;
// probably need to think about copy operations also, as the move disables them
Base(const Base&) = default;
Base& operator=(const Base&) = default;
};
我强烈推荐可能对移动语义贡献最大的人的这个演讲:http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014
I highly recommend this talk by the person who contributed probably the most to the move semantics: http://www.slideshare.net/ripplelabs/howard-hinnant-accu2014
或者,如果您能亲自动手,您应该阅读 Scott Meyers 的优秀著作Effective Modern 中的条款 17:了解特殊成员函数生成C++.这个问题得到了很好的解释.
Or, if you can get your hands on, you should read the Item 17: Understand special member function generation from Scott Meyers' excellent book Effective Modern C++. This issue is excellently explained.
PS:我认为您应该多考虑一下您的基类.大多数情况下,您应该使用抽象类,因此无需复制/移动它们的实例.
PS: I think you should think a bit more about your base classes. Most of the time, you should use abstract classes, so there will be no need to copy/move instances of them.
PSS:我认为默认情况下,析构函数在 C++11/14 中被标记为 noexcept
,所以不明确指定它不会导致任何问题:
PSS: I think by default destructors are marked noexcept
in C++11/14, so not explicitly specifying it shouldn't cause any problems:
继承构造函数和隐式声明的默认值构造函数、复制构造函数、移动构造函数、析构函数、复制赋值运算符,移动赋值运算符都是noexcept(true) 默认情况下,除非他们需要调用一个函数即 noexcept(false),在这种情况下,这些函数是noexcept(false).
Inheriting constructors and the implicitly-declared default constructors, copy constructors, move constructors, destructors, copy-assignment operators, move-assignment operators are all noexcept(true) by default, unless they are required to call a function that is noexcept(false), in which case these functions are noexcept(false).
这篇关于C++11 虚拟析构函数和移动特殊函数的自动生成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:C++11 虚拟析构函数和移动特殊函数的自动生成
基础教程推荐
- 如何“在 Finder 中显示"或“在资源管理器中显 2021-01-01
- 从 std::cin 读取密码 2021-01-01
- 如何使图像调整大小以在 Qt 中缩放? 2021-01-01
- 为 C/C++ 中的项目的 makefile 生成依赖项 2022-01-01
- 使用从字符串中提取的参数调用函数 2022-01-01
- 为什么语句不能出现在命名空间范围内? 2021-01-01
- 如何在不破坏 vtbl 的情况下做相当于 memset(this, ...) 的操作? 2022-01-01
- 在 C++ 中循环遍历所有 Lua 全局变量 2021-01-01
- 管理共享内存应该分配多少内存?(助推) 2022-12-07
- Windows Media Foundation 录制音频 2021-01-01