C++ 新的对象数组,其构造函数需要C++;
在开始我的问题之前,让我说我知道我可以使用标准库或gsl库轻松解决我的问题(例如,C++ 新的对象数组,其构造函数需要C++;,c++,constructor,dynamic-memory-allocation,C++,Constructor,Dynamic Memory Allocation,在开始我的问题之前,让我说我知道我可以使用标准库或gsl库轻松解决我的问题(例如,std::Vector)。但我正在努力学习C++和动态内存分配,所以我想知道是否有一种方法可以在不使用向量或类似的情况下解决它。 我有一个层类,它包含在创建对象时确定的许多神经元(通过动态内存分配): 问题是网络构造函数失败,因为\u layers=new Layer[nb\u layers]尝试调用没有参数的构造函数,但失败了。 另外,\u layers[i]=新层(nb\u neurons[i])失败,因为“没
std::Vector
)。但我正在努力学习C++和动态内存分配,所以我想知道是否有一种方法可以在不使用向量或类似的情况下解决它。
我有一个层
类,它包含在创建对象时确定的许多神经元(通过动态内存分配):
问题是网络构造函数失败,因为\u layers=new Layer[nb\u layers]
尝试调用没有参数的构造函数,但失败了。
另外,\u layers[i]=新层(nb\u neurons[i])
失败,因为“没有可行的重载”=”,我不理解。
如何使用动态内存分配而不是std::Vector
解决此问题
最后,我实现动态内存分配的方法是否正确,并且没有任何内存泄漏?我想知道我的unsigned int*nb_neurons
在网络构造函数中会发生什么,因为这些值正在使用,但我从不删除它。
(作为背景,我多年来一直在用Java、Python和PHP编写代码)
多谢各位
我需要创建一个由n层组成的网络,每个层包含不同数量的神经元(作为长度为n的数组传递):
对于固定的层
对象数组,您将无法做到这一点。尽管有一种语法可供new[]
操作符使用相同的构造函数值初始化所分配数组的所有元素,但没有语法可用于使用不同的值初始化它们,至少当值来自另一个数组时是这样
要执行您所要求的操作,您必须创建一个层*
指针数组(或者更好,在C++11及更高版本中创建一个std::unique_ptr
对象数组),然后根据需要使用不同的构造函数值动态创建每个层
对象。您很快就能做到这一点,但您只是在数组声明中缺少了一个额外的间接层:
类网络{
私人:
无符号整数层;
层**\u层;//线
_layers[i] = new Layer(nb_neurons[i]);
有两个问题
类型不匹配。\u layers[i]
是一个对象,而RHS是一个指针
\u layers[i]
是一个const
对象。因此,在初始化之后,您无法为其分配任何内容
您可以使用
std::vector<Layer*> _layers;
std::vector\u层;
为了更好更容易地管理内存,请使用智能指针向量
std::vector<std::unique_ptr<Layer>> _layers;
std::vector\u层;
或
std::vector\u层;
您可以这样做,但必须使用placement new。让我们看看如何做到这一点
首先,我们将创建一个表示内存块的类。它将与placement new一起用于创建层。它不需要任何函数,因为它只是用于分配适当大小和对齐的内存
template<size_t count, size_t alignment>
struct alignas(alignment) memory {
std::array<unsigned char, count> bytes;
};
我们可以使用它来创建一个表示层数组的类。我将其分为四个部分:
-数据成员(指向内存的指针和存储层数的变量
-成员函数(用于访问各个层)
-构造函数(用于从大小列表中生成layeraray
)
-析构函数(用于删除我们分配的内存块)
如果你来自java环境,你最好忘记你在那里学到的一切,把C++当作一种全新的语言。一方面,<代码>新< /C> >被认为是现代C++中的一个坏习惯,你肯定不想用“代码<新< /COD>”创建每个对象。对于没有默认构造函数的对象数组:对于可能的m埃默里泄密:(并非真正的泄密,但仍然是一个问题)向量是动态内存分配。是的,我知道“new”不是C++核心指南推荐的,我只是想在它转到其他方法之前先学习它是如何工作的。我发布了一个答案,它显示了如何使用新的布局来使用连续的一系列数组。它更贴近你原来想要的。estion,并且您没有使用指针数组所带来的额外间接层(这意味着它也更具内存效率)。谢谢,这非常清楚(我将查找3/5/0规则,这似乎非常重要)。我对std::unique\u ptr有一个问题,我知道它很有用,因为如果指针变得不可访问,它会删除对象,但是如果您正确实现指针并删除所有内容,那么它们在任何方面都有用吗?@aurelian Smart pointers允许您编写更安全的内存管理代码。您可以随时替换delete
/删除[]/Case>用<代码> STD::UNQuYGYPTR (或<代码> STD::SysDypPTR ),现代C++代码应避免调用<代码>新< /COD> >代码>新[]
尽可能直接。在这种情况下,一个std::vector
将是一个更好的选择,但是std::unique\u ptr
提供了一个折衷方案,因此您仍然可以手动使用new
/new[]
而不必手动使用delete
/delete[]
。
std::vector<std::unique_ptr<Layer>> _layers;
std::vector<std::shared_ptr<Layer>> _layers;
template<size_t count, size_t alignment>
struct alignas(alignment) memory {
std::array<unsigned char, count> bytes;
};
using layer_memory = memory<sizeof(Layer), alignof(Layer)>;
class LayerArray {
//* PART ONE: DATA MEMBERS *//
private:
layer_memory* mem;
size_t count;
//* PART TWO: MEMBER FUNCTIONS *//
public:
// Get a pointer to the memory as an array of Layers
Layer* data() {
return reinterpret_cast<Layer*>(mem);
}
Layer const* data() const {
return reinterpret_cast<Layer const*>(mem);
}
// Dereference the i-th block of memory as a Layer
Layer& operator[](size_t i) {
return data()[i];
}
Layer const& operator[](size_t i) const {
return data()[i];
}
//* PART THREE: CONSTRUCTORS *//
// Convenience constructor from initializer list
LayerArray(std::initializer_list<unsigned> counts)
: LayerArray(counts.begin(), counts.size()) {}
// Move constructor
LayerArray(LayerArray&& other)
: mem(other.mem)
, count(other.count)
{
other.mem = nullptr;
other.count = 0;
}
// Constructor that uses an array of layer sizes
LayerArray(const unsigned int* layer_size_counts, size_t count)
: mem(new layer_memory[count])
, count(count)
{
for(size_t i = 0; i < count; i++) {
auto layer_size = layer_size_counts[i];
// Create the new layer in the i-th block of memory
new (mem + i) Layer(layer_size);
}
}
//* PART FOUR: DESTRUCTOR *//
~LayerArray() {
for(size_t i = 0; i < count; i++) {
Layer& layer = data()[i]; // Get the layer
layer.~Layer(); // Manually call the destructor for the Layer
}
delete[] mem;
}
};
int main() {
// Create an array of layers with the specified sizes
LayerArray layers { 50, 50, 50, 10, 3 };
// Do other stuff...
}