我正在学习c ++中的动态内存分配过程。
1.如何在没有事先了解大小的情况下声明数组的动态内存分配?
2.假设我使用一个变量动态地为数组分配内存但是稍后在程序中减少了数组的大小。是否会自动取消内存分配?
如果没有,那么如何更新呢?
如果这些是愚蠢的问题,请饶恕我。如果你回答请包括一个示例程序。
答案 0 :(得分:0)
如果确实选择动态分配内存,则需要对数组使用运算符new [],该数组在c ++中被视为与非数组类型的新运算符不同。
1)以下是如何动态分配数组的示例:
int length = 10;
int *myArray = new int[length];
// do something
myArray[0] = 42;
完成后,您需要使用delete []:
释放内存delete[] myArray;
2)不,除非你使用智能指针(What is a smart pointer and when should I use one?),否则C ++中没有动态分配内存的自动解除分配。
如果要调整阵列大小,则必须手动执行:
delete[] myArray;
int newLength = 5;
myArray = new int[newLength];
答案 1 :(得分:0)
正如@frameworks指出的那样,你需要运算符new[]
来为数组分配内存,你需要调用delete[]
来释放那个内存。如果delete[]
没有new[]
,您的程序将泄漏内存。 (如果有多个delete[]
要求单个new[]
,则您的程序将发生段错误/崩溃。)
但是,确保分配有new[]
(或new
)的内存始终被相应的delete[]
(或delete
)清理并不总是微不足道的,并且只被清理一次。对于具有复杂控制流的代码,指针传递的代码或可能在new[]
和delete[]
之间抛出异常的情况尤其如此。
换句话说:只要有new
,就可能有泄漏。
为了省去手动内存管理的所有麻烦,请改用std::vector
。此容器会为您处理内存管理。
每当你想写一些类似
的东西时int *myArray = new int[3];
//do something with myArray
delete[] myArray;
你应该写
std::vector<int> myArray;
//do something with myArray
代替。你不需要在这里删除,像std::vector::push_back()这样的方法会处理底层结构所需的大小调整,如果它没有提供足够的空间来容纳所有推送的值。您还可以使用std::vector::shrink_to_fit()删除未使用的元素。 (但是,shrink_to_fit是一个减少内部大小的非绑定请求。也就是说,编译器之间的结果可能会有所不同。)
答案 2 :(得分:0)
正如 干杯和hth 在评论中说,最好的方法是使用std::vector
,它负责内存管理本身。
- 如何在不事先了解大小的情况下声明数组的动态内存分配?
醇>
这个想法是,如果您不知道大小,则不分配任何内存,并且在向其添加元素时,您可以增加内存,请参阅下面的示例。
实施类似std::vector
的类:
vector
使用两种尺寸,一种是size
,即vector
当前持有的元素数量,capacity
是您vector
的元素数量1}}可以保持(内存分配给capacity
)
先决条件:我假设您知道基本内存分配和解除分配,您可以使用new
运算符分配内存,并使用{{取消分配1}} operator。
注意:为了简单起见,我正在为delete
实现一些仅使用MyIntVector
数组的方法,但您始终可以实现模板化的类。
<强>实施强>:
您可以为您的类提供默认构造函数,它不会分配任何内存,将int
和size
设置为capacity
(客户端程序可以使用此构造函数,如果大小未知)。
在创建0
size
用作起始size
。
还提供一个析构函数来完全取消分配已分配的内存。
MyIntVector
现在,如果您想为class MyIntVector{
size_t _size;
size_t _capacity;
int* _data;
public:
MyIntVector(){
_size = 0;
_capacity = 0;
_data = nullptr;
}
MyIntVector(size_t size){
_size = size;
_capacity = size;
_data = new int[_capacity];
}
~MyIntVector(){
if (_data){
delete[] _data;
}
_data = nullptr;
_size = _capacity = 0;
}
};
添加一些元素,可以实现MyIntVector
功能,例如push_back
。
std::vector
class MyIntVector{
//...
void push_back(int elem){
if (_size >= _capacity){
// Oops, we're out of memory, let's make room for this elem first
resize(_capacity > 0? _capcity * 2 : 10);
}
// Now, there's enough memory to hold this elem
_size++;
_data[_size - 1] = elem;
}
void resize(size_t newCapacity){
if (newCapacity != _capacity){
if (_size == 0){
_capacity = newCapacity;
_data = new int[_capacity];
}
else {
// create a temporary array to hold the elements of _data
int* temp = new int[_size];
for (size_t i = 0; i < _size; i++)
temp[i] = _data[i];
// de-allocate the memory of _data
delete[] _data;
// allocate memory in _data with newCapacity
_capacity = newCapacity;
_data = new int[_capacity];
// copy the elements of temporary array back in _data
for (size_t i = 0; i < _size; i++){
_data[i] = temp[i];
}
// done with the temporary array, de-allocate it.
delete[] temp;
temp = nullptr;
}
}
}
//...
};
功能:
我在上面的例子中实现的push_back
函数,它看到是否可以将新元素添加到push_back
而不需要分配任何新内存,如果没有,它只是将MyIntVector
增加_size
并复制元素。如果需要新的内存,它会调用容量加倍的1
方法(如果已经有一些已分配的内存。)或一些硬编码的值,比如resize
(如果是,没有任何先前分配的内存)
10
功能:
resize
函数以resize
为参数,并在newCapacity
中分配所需的内存,主要是创建一个临时数组来保存_data
的元素,然后在_data
中取消分配内存,在_data
中分配更大的内存,从_data
复制回temp
并取消分配_data
数组。
注意 :只有在增加 temp
时才应使用resize
的此实现,它应该<强烈>不要求减少 _capacity
因此,我们的想法是,您可以通过使用临时数组来保存元素,取消分配前一个数组,分配新数组以及从临时数组中复制元素来增加数组的大小。您可以实施_capacity
为练习提供的不同方法。
如果您不想在每次增加容量时取消分配和重新分配内存,您可以随时实现链接列表,here用于实现链接列表的教程,但是链接列表的一个缺点是,您无法像从阵列中那样随机访问链接列表中的元素。
- 假设我使用一个变量动态地为数组分配内存,但是稍后在程序中减少了数组的大小。是否会自动取消分配内存?
醇>
没有自动取消内存分配,如果需要,您必须手动减少std::vector
。
您可以在_capacity
课程中添加pop_back
方法来删除元素。
MyIntVector
您可以在返回元素之前手动减少class MyIntVector{
// ...
int pop_back(){
if (_size == 0){
// You can throw some exception here if you want.
throw exception("No elements found");
}
_size--;
return _data[_size];
}
// ...
};
。
您还可以为_capacity
类提供下标运算符[]
的实现,以便在数组中提供随机访问。