当前位置:  开发笔记 > 编程语言 > 正文

使用受保护的析构函数动态分配类数组

如何解决《使用受保护的析构函数动态分配类数组》经验,为你挑选了2个好方法。

如果我有一个类定义的类

class A {
protected:
    ~A(){ }
};

然后我可以动态分配个人以及像这样的对象数组

A* ptr1 = new A;
A* ptr2 = new A[10];

但是,当我为这个类定义构造函数时

class A {
public:
    A(){}
protected:
    ~A(){ }
};

然后我可以创建单个对象

A* ptr = new A;

但是当我尝试动态分配对象数组时

A* ptr = new A[10];

编译器(gcc-5.1和Visual Studio 2015)开始抱怨A :: ~A()是不可访问的.

谁能解释一下: -

1-为什么定义和未定义构造函数的行为差异.

2-定义构造函数时,为什么允许创建单个对象而不是对象数组.



1> Matteo Itali..:

new根据C++ 11,§5.3.417 拒绝带有受保护的析构函数的数组是正确的:

如果new-expression创建一个对象或类类型的对象数组,则对分配函数,释放函数(12.5)和构造函数(12.1)进行访问和歧义控制.如果新表达式创建了类类型的对象数组,则对析构函数进行访问和模糊控制(12.4).

(重点补充;几乎完全相同的措辞用于C++ 03,§5.3.416; C++ 14移动了一些东西,但这似乎没有改变问题的核心 - 见@Baum mit Augen的回答)

这是因为new[]只有在构造了所有元素的情况下才能成功,并且在其中一个costructor调用失败的情况下希望避免泄漏对象; 因此,如果它设法构造 - 比如说 - 前9个对象但是第10个对象因异常而失败,它必须在传播异常之前破坏前9个.

请注意,如果构造函数被声明为逻辑上不需要此限制noexcept,但在这方面标准似乎没有任何异常.


所以,这里gcc在第一种情况下在技术上是错误的,就标准而言,也应该被拒绝,尽管我认为"道德"gcc做正确的事(因为在实践中没有办法A可以抛出的默认构造函数).


关于标准措辞,使用`noexcept`构造函数可能不足以保证在构造数组期间不会抛出任何异常.构造函数可能有一个参数,该参数具有在调用中使用的默认参数,并且该初始化可能会抛出.我不认为处理像问题中的例子这样的简单案例值得增加措辞的复杂性.此外,这里指定的方式与[class.base.init]中处理其他类型子对象的方式一致.cc @Walter

2> Baum mit Aug..:

事实证明,gcc在这里是不正确的.在N4141(C++ 14)中,我们有:

如果new-expression创建了类类型的对象数组,则可能会调用析构函数(12.4).

(5.3.4/19 [expr.new])和

如果可能调用的析构函数被删除或无法从调用的上下文访问,则程序格式不正确.

(12.4/11 [class.dtor]).所以两个数组都应该被拒绝.(Clang确实做到了,活着.)

原因是,正如其他人和我以前的错误答案所提到的那样,类类型元素的构造可能会因异常而失败.当发生这种情况时,必须调用所有完全构造的元素的析构函数,因此必须可以访问析构函数.

当使用operator new(不使用[])分配单个元素时,该限制不适用,因为如果单个构造函数调用失败,则不能完全构造该类的实例.

推荐阅读
mobiledu2402851323
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有