为什么我不能分配一个 class 的数组,其中包含 deleted 或 private 析构函数?

Why can't I allocate an array of a class with deleted or private destructor?

我最近 运行 在工作中遇到了这个问题。我正在使用的库使用引用计数对象并实现了自己的处理方式。部分实现是库的每个 class 都有一个私有析构函数。我猜这是为了防止在堆栈上创建对象,因为库会自动管理对象的生命周期(它是一个场景图)。

无论如何,我想在堆上分配一个这样的数组 class 并且 运行 进入以下问题:

#include <iostream>

using namespace std;

    class test
    {
    public:
        test() {
            cout << "ctor" << endl;
        }

        //~test() = delete; also doesnt work

    private:
        ~test()
        {
            cout << "dtor" << endl;
        }

    };

    int main()
    {
        //works
        auto oneInstance = new test;

        //doesnt work
        auto manyInstances = new test[3];
    }

数组分配使用 GCC 产生以下错误:

source_file.cpp: In function ‘int main()’:
source_file.cpp:15:5: error: ‘test::~test()’ is private
     ~test()
     ^
source_file.cpp:26:36: error: within this context
     auto manyInstances = new test[3];
                                    ^

为什么析构函数需要是 public/available 才能在堆上分配这个 class 的数组?当只分配单个实例时,它工作正常,就像在前面的行中一样。我也尝试使用更现代的 "delete" 语法,但它产生了相同的结果。

new[] 运算符中是否有我不知道的魔法?

编辑:

感谢您的快速帮助。我想知道为什么这段代码不打印 "dtor" 两次:

#include <iostream>

using namespace std;

class test
{
public:
    test() {
        static int allocations = 0;
        ++allocations;

        if(allocations == 3)
        {
            //produce exception
            throw 1;
        }
        cout << "ctor" << endl;
    }

    ~test()
    {
        cout << "dtor" << endl;
    }

};

int main()
{
    //works
    auto oneInstance = new test;

    //doesnt work
    try {
    auto manyInstances = new test[3];
    }
    catch(...)
    {
            cout << "error?";
    }
}

这会打印:

ctor ctor dtor error?

因为异常,new[]的数组版本必须在异常传播时去调用先前分配的元素的析构函数以确保异常安全。单个元素 new 不需要这样做。如果分配失败,它就失败了,不需要销毁任何东西。

§ 8.3.4 新 [expr.new/20]

If the new-expression creates an array of objects of class type, the destructor is potentially invoked


关于您的编辑,请参阅以下引用自 C++17 标准的内容

§ 8.17 抛出异常 [expr.throw/4]

If no exception is presently being handled, evaluating a throw-expression with no operand calls std::terminate()


关于您的第二次编辑,您错过了通过 new(不是 new[])创建的 test 实例的计数,该实例导致 [=13] 的第一个实例=] 正在创建,这就是关于结构数量的混淆的来源。