Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/158.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在C++;11_C++_C++11_Virtual Destructor - Fatal编程技术网

C++ 在C++;11

C++ 在C++;11,c++,c++11,virtual-destructor,C++,C++11,Virtual Destructor,关于C++11/14标准,在幻灯片15中,作者写道“许多经典的编码规则在C++11中不再适用”。他列举了三个例子,我同意三个法则和内存管理 然而,他的第二个例子是“具有虚拟成员的虚拟析构函数”(仅此而已)这意味着什么?我知道,如果我们有类似于 Base *b = new Derived; ... delete b; 这里有很好的解释: 但是现在在C++11中,如果您有虚拟成员,那么声明虚拟析构函数没有用吗?链接的文章显示了相关代码: std::unique_ptr<Derived>

关于C++11/14标准,在幻灯片15中,作者写道“许多经典的编码规则在C++11中不再适用”。他列举了三个例子,我同意三个法则和内存管理

然而,他的第二个例子是“具有虚拟成员的虚拟析构函数”(仅此而已)这意味着什么?我知道,如果我们有类似于

Base *b = new Derived;
...
delete b;
这里有很好的解释:


但是现在在C++11中,如果您有虚拟成员,那么声明虚拟析构函数没有用吗?

链接的文章显示了相关代码:

std::unique_ptr<Derived> { new Derived };
std::unique_ptr{new Derived};
存储的删除程序是
std::default_delete
,它不要求
Base::~Base
是虚拟的

现在您可以将其移动到
unique\u ptr
,它还将移动
std::default\u delete
,而无需将其转换为
std::default\u delete

我认为这与演示中其他地方提到的“零规则”有关


如果您只有自动成员变量(即,对于可能是原始指针的成员,使用
shared_ptr
unique_ptr
),那么您不需要编写自己的复制或移动构造函数或赋值运算符——编译器提供的默认值将是最佳的。使用类内初始化,您也不需要默认构造函数。最后,您根本不需要编写析构函数,不管是虚拟的还是非虚拟的。

作为幻灯片的作者,我将尝试澄清

如果编写代码时使用
new
显式分配
派生的
实例,并使用基类指针使用
delete
销毁它,则需要定义一个
虚拟的
析构函数,否则最终将不完全销毁
派生的
实例。但是,我建议完全避免使用
new
delete
,并专门使用
shared\u ptr
来引用堆分配的多态对象,如

shared_ptr<Base> pb=make_shared<Derived>();
shared_ptr pb=make_shared();
这样,即使使用
shared\u ptr
表示,共享指针也会跟踪要使用的原始析构函数。一旦最后一个引用的
shared\u ptr
超出范围或被重置,将调用
~Derived()
,并释放内存。因此,您不需要将
~Base()
设置为虚拟

unique_ptr
make_unique
不提供此功能,因为它们不提供有关删除器的
shared_ptr
机制,因为unique指针简单得多,以最低的开销为目标,因此不存储删除器所需的额外函数指针。使用
unique\u ptr
时,deleter函数是类型的一部分,因此,带有deleter的uniqe\u ptr引用
~派生的
将与使用默认deleter的
unique\u ptr
不兼容,如果
~Base
不是虚拟的,这对于派生实例来说无论如何都是错误的

我提出的个人建议,是为了易于遵循,并一起遵循。他们试图通过让所有资源管理由库组件和编译器生成的代码来完成,从而生成更简单的代码

定义类中的(虚)析构函数,将禁止编译器提供的移动构造函数/赋值操作符,并且可能禁止编译器提供的复制构造函数/赋值操作符在C++的未来版本中。使用

=default
恢复它们变得很容易,但看起来仍然像很多样板代码。最好的代码是您不必编写的代码,因为它不会出错(我知道该规则仍有例外)

将“不要定义(虚拟)析构函数”总结为我的“零规则”的推论:

每当您在现代C++中设计多态(OO)类层次结构,并希望/或需要在堆上分配实例并通过基类指针访问它们时,使用<代码> MaMaJuffSyd()/Script >实例化它们,并<代码> SyddyPtR <代码>以保持它们。这允许您保持“零规则”

这并不意味着您必须分配堆上的所有多态对象。例如,定义一个以
(Base&)
为参数的函数,可以使用一个本地
派生的
变量调用,而不会出现问题,并且相对于
Base
的虚拟成员函数,它的行为将是多态的


在我看来,动态OO多态性在许多系统中被过度使用。当我们使用C++时,我们不应该像java那样编程,除非我们遇到问题,其中堆分配对象的动态多态性是正确的解决方案。p> 要回答具体问题

但是现在在C++11中,如果您有虚拟成员,那么声明虚拟析构函数是没有用的吗

在C++11核心语言中,对虚拟析构函数的需求没有改变。如果要使用基指针删除派生对象,则必须将析构函数声明为虚拟


幻灯片中的语句给人的印象是,C++11以某种方式改变了虚拟析构函数的行为——事实并非如此。正如作者所阐明的,它仅在使用
共享\u ptr
时适用。但在冗长的解释中,虚拟析构函数仍然是必需的(除了使用
shared\u ptr
)这一事实被淡化了

这只是一个猜测,但在使用智能指针时,可以安排调用正确的析构函数,即使基析构函数不是虚拟的。这是在
shared_ptr
中开箱即用的情况下发生的。大意是三的规则或不再需要虚拟析构函数的声明非常简单