new和delete运算符一次只分配/释放一个对象,但是某些应用需要以此为很多对象分配内存的功能。
C++中制定了两种分配/释放多个对象的机制!分别是:new[]/delete[] 和 allocator类。
其中new[]/delete[] 再分配内存的时候就初始化对象;allocator类将内存的分配和对象的初始化分离。
new[]的初始化
int * p = new int[get_size()];
int * q = new int[100];//默认初始化,100个未初始化的int
int * s = new int[100](); //值初始化,100个0
int * m = new int[10]{1,2,3,4,5,6,7,8,9}; //1,2,3,4,5,6,7,8,9,0(0是值初始化)
花括号列表形式的初始化器用来初始化动态数组的开始部分元素。如果初始化器给出的元素大于总的元素数目,则new表达是会出错,不会分配任何内存。当小于总的元素数目的时候,后面的生于元素将会进行值初始化。
delete[] 释放动态数组
typedef int arrT[100];
int * p = new arrT;
delete[] p;
当我们释放一个指向数组的指针的时候,空括号是必须的。因为:它指示编译器此指针指向一个对象数组的第一个元素!如果我们忽略了方括号,其行为是未定义的。
数组的元素的销毁是逆序的。最后一个元素首先被销毁,然后是倒数第二个,以此类推。
智能指针和动态数组
unique_ptr
unique_ptr<int[]> p(new int[100]()); //分配
p.reset() ; //释放
unique_ptr使用下标访问数组中的元素
![](/qrcode.jpg)
unique_ptr<int[]>p(new int[10]);
for(size_t i = 0;i != 10;i++)
{
up[i] = i; //使用下标进行赋值操作
}
shared_ptr 本来是不支持管理一个动态数组的。但是如果我们需要进行这种操作就必须要给它传递一个删除器;
shared_ptr<int>sp(new int[10],[](int* P){delete[] p;});
sp.reset(); // 使用lambda作为删除器,释放数组
shared_ptr 使用get()访问数组元素;
for(size_t i = 0;i != 10;++i)
{
*(sp.get()+ i) = i; //通过get()返回内置指针,访问数组元素
}
allocator类 primer p428
其实很简单,将内存的创建+对象的构造分离开来;也就是将 对象的析构+内存的释放分离开来!
内存创建:allocate() 然后返回第一个元素的起始地址
对象的构造:construct() 参数一 位置指针,参数二 对象
对象的析构:destory() 传递指针
内存释放:deallocate() //传递给deallocate的指针必须是之前某次allocate返回的指针,因此在deallocate之前我们必须要检查该指针是否为空
举个栗子:
#include <iostream>
#include <memory>
using namespace std;
class Animal
{
public:
#if 1 //即使为0,没有默认构造也是可以,
Animal() : num(0)
{
cout << "Animal constructor default" << endl;
}
#endif
Animal(int _num) : num(_num)
{
cout << "Animal constructor param" << endl;
}
~Animal()
{
cout << "Animal destructor" << endl;
}
void show()
{
cout << this->num << endl;
}
private:
int num;
};
int main()
{
allocator<Animal> alloc; //1.
Animal *a = alloc.allocate(5); //2.
//3.
alloc.construct(a, 1);
alloc.construct(a + 1);
alloc.construct(a + 2, 3);
alloc.construct(a + 3);
alloc.construct(a + 4, 5);
//4.
a->show();
(a + 1)->show();
(a + 2)->show();
(a + 3)->show();
(a + 4)->show();
//5.
for (int i = 0; i < 5; i++)
{
alloc.destroy(a + i);
}
//对象销毁之后还可以继续构建,因为构建和内存的分配是分离的
//6.
alloc.deallocate(a, 5);
cin.get();
return 0;
}
输出
Animal constructor param
Animal constructor default
Animal constructor param
Animal constructor default
Animal constructor param
1
0
3
0
5
Animal destructor
Animal destructor
Animal destructor
Animal destructor
Animal destructor