带有需要 C++ 参数的构造函数的新对象数组

Dra*_*ade 5 c++ constructor dynamic-memory-allocation

在开始我的问题之前,我要说的是,我知道我可以使用标准库或 gsl 库(例如std::Vector)轻松解决我的问题。但我正在尝试学习 C++ 和动态内存分配,所以我想知道是否有一种方法可以在不使用 Vector 或类似的东西的情况下解决它。

我有一个Layer类,其中包含创建对象时确定的多个神经元(通过动态内存分配):

class Layer {
private:
    unsigned int _size;
    const Neuron* _neurons;

public:
    Layer(unsigned int size);
    ~Layer();

    const Neuron* getNeuron(unsigned int index) const;
};

Layer::Layer(unsigned int size) {
    _size = size;
    _neurons = new Neuron[size];
}

const Neuron* Layer::getNeuron(unsigned int index) const {
    Expects(index < _size);

    return &_neurons[index];
}

Layer::~Layer() {
    delete[] _neurons;
}
Run Code Online (Sandbox Code Playgroud)

现在的挑战是在Network课堂上:我需要创建一个 n 层网络,每个层包含不同数量的神经元(作为长度为 n 的数组传递):

class Network {
private:
    unsigned int _nb_layers;
    const Layer* _layers;

public:
    Network(unsigned int nb_layers, unsigned int* nb_neurons);
    ~Network();

    const Layer* getLayer(unsigned int index) const;
};

Network::Network(unsigned int nb_layers, unsigned int *nb_neurons) {
    _nb_layers = nb_layers;
    _layers = new Layer[nb_layers];

    for(int i = 0; i < nb_layers; i++) {
        _layers[i] = new Layer(nb_neurons[i]);
    }
}

const Layer* Network::getLayer(unsigned int index) const {
    Expects(index < _nb_layers);

    return &_layers[index];
}

Network::~Network() {
    delete _layers;
}
Run Code Online (Sandbox Code Playgroud)

问题是 Network 构造函数失败,因为_layers = new Layer[nb_layers]尝试调用不带参数的构造函数,但失败了。另外,_layers[i] = new Layer(nb_neurons[i])失败是因为“没有可行的重载'='”,我不明白。如何使用动态内存分配而不是解决此问题std::Vector

最后,我实现动态内存分配的方式是否正确并且没有任何内存泄漏?我想知道unsigned int *nb_neurons网络构造函数中会发生什么,因为这些值正在被使用,但我永远不会删除它。(作为背景,我多年来一直在使用 Java、Python 和 PHP 进行编码)

非常感谢!

Rem*_*eau 4

我需要创建一个 n 层网络,每层包含不同数量的神经元(作为长度为 n 的数组传递):

您将无法使用固定的Layer对象数组来做到这一点。尽管有一种语法可供运算符使用相同的new[]构造函数值来初始化已分配数组的所有元素,但没有语法可以使用不同的值来初始化它们,至少当这些值来自另一个数组时不会。

要执行您所要求的操作,您必须创建一个Layer*指针数组(或者更好的是,C++11 及更高版本中的对象数组std::unique_ptr<Layer>),然后Layer根据需要使用不同的构造函数值动态创建每个对象。您已经接近这样做了,但您只是在数组声明中缺少了额外的间接层:

class Network {
private:
    unsigned int _nb_layers;
    Layer** _layers; // <-- DYNAMIC ARRAY OF POINTERS, NOT OBJECTS!

public:
    Network(unsigned int nb_layers, unsigned int* nb_neurons);
    ~Network();

    const Layer* getLayer(unsigned int index) const;
};

Network::Network(unsigned int nb_layers, unsigned int *nb_neurons) {
    _nb_layers = nb_layers;
    _layers = new Layer*[nb_layers]; // <-- ALLOCATE ARRAY OF POINTERS FIRST

    for(int i = 0; i < nb_layers; i++) {
        _layers[i] = new Layer(nb_neurons[i]); // <-- THEN MAKE EACH POINTER POINT TO AN OBJECT
    }
}

const Layer* Network::getLayer(unsigned int index) const {
    Expects(index < _nb_layers);

    return _layers[index];
}

Network::~Network() {
    for (int i = 0; i < _nb_layers; ++i)
        delete _layers[i]; // <-- NEED TO FREE EACH OBJECT FIRST
    delete[] _layers; // <-- THEN FREE THE ARRAY ITSELF
}
Run Code Online (Sandbox Code Playgroud)

在 C++11 及更高版本中,您可以这样做:

class Network {
private:
    unsigned int _nb_layers;
    std::unique_ptr<std::unique_ptr<Layer>[]> _layers;

public:
    Network(unsigned int nb_layers, unsigned int* nb_neurons);
    // ~Network(); // <-- NOT NEEDED!

    const Layer* getLayer(unsigned int index) const;
};

Network::Network(unsigned int nb_layers, unsigned int *nb_neurons) {
    _nb_layers = nb_layers;
    _layers.reset( new std::unique_ptr<Layer>[nb_layers] );

    for(int i = 0; i < nb_layers; i++) {
        _layers[i].reset( new Layer(nb_neurons[i]) );
        // or, in C++14 and later:
        // _layers[i] = std::make_unique<Layer>(nb_neurons[i]);
    }
}

const Layer* Network::getLayer(unsigned int index) const {
    Expects(index < _nb_layers);

    return _layers[index].get();
}

/*
Network::~Network()
{
    // NOTHING TO DO HERE!
}
*/

Run Code Online (Sandbox Code Playgroud)

顺便说一句,你们的两个班级都违反了3/5/0 规则。这两个类都没有实现复制构造函数或复制赋值运算符,以便将各自的数组从一个类实例复制到另一个类实例。或者,对于 C++11 及更高版本,移动构造函数和移动赋值运算符将各自的数组从一个类实例移动到另一个类实例。