new和数组
/*
1. c++ 提供了两种一次分配一个对象数组的方法,
C++定义了另一种new 的表达式,可以分配并初始化一个对象数组
标准库中有一个allocator类, 允许我们将分配和初始化分离
2. 动态数组是new在分配的时候可以带入参数
void f(int a[])
{
int *p = new int[sizeof(a)]; //载入的参数不同每次分配的数组长度都不一样
}
//严格意义上说并不是动态数组, 因为new int[]返回的是一个int类型的指针, 所以不是一个数组
//并不能调用begin和end, 所以也不能用for的范围语句来处理动态数组的元素
//动态数组并不是数组类型
*/
初始化动态分配对象数组
int *p = new int[10];//十个未初始化的int
int *p = new int[10]();//十个为0的int
int *p = new string[2];//..
int *p = new string[2]();//
c++11中
int *p = new int[2]{2,2};//后跟大括号初始化
/*
如果在这个过程中出现大括号初始化器里面的初始化内容小于定义的长度, 那么其余按照值初始化
如果大于, 那么会抛出异常, 并且new申请失败,
异常类型为: bad_array_length的异常, 类似于 bad_alloc此异常定义在头文件new中
*/
动态分配一个空数组是合法的
char a[0]; //错误, 不能定义长度为0的数组
char *cp = new char[0];// 正确但是cp 不能解引用
释放动态数组
char *p = new int;
char *p2 = new int[2];
delete []p;
delete []p2;
//在释放的时候如果对象指向不明确, 那么最好是加上括号. 防止释放过程不完全,
使用智能指针管理动态数组
/*
1. 推荐使用unique_ptr <T[]> u;//当u销毁管理的指针的时候回自动调用delete[]
2. 使用shared_ptr 管理, 自己定义删除函数
shared_ptr<T[]> sh(new T[size],[](T *){delete []T;});
使用lambda表达式
*/
allocator类
new有一些局限性, 表现在他把内存分配和对象构造放在一起, delete也将内存释放和对象析构放在一起
当分配很大的内存的时候我们希望将内存分配和对象构造分开, 这意味着我们可以分配大块内存, 但是真正需要时才真正执行对象创建操作
allocator类
/*
定义: memory中
作用: 提供内存分配和对象构造分离开来, 他提供一种类型感知的内存分配方法, 分配的内存是原始的, 未构造的,
*/
allocator<string> alloc;// 可分配string的allocator的对象
auto const p = alloc.allocate(n);// 分配n个未初始化的string
alloc.deallocate(p,n);//释放T*中P开始的内存, p必须是之前allocate返回的指针, n必须是创建时的大小, 调用deallocate之前必须调用, alloc.destroy(p);//
alloc.construct(p,arg); //p必须是一个类型为T*的指针, 指向一块原始内存, arg用来在p创建的内存中构造一个对象
allocator分配未构造的内存
#include <iostream>
#include <memory>
#include <string>
using namespace std;
int main()
{
const int n = 10;
allocator<string> alloc;
auto const p = alloc.allocate(n);
auto q = p;
alloc.construct(q++);//第一个为空的string
alloc.construct(q++,10,'c');//第二个为含有10 个c
alloc.construct(q++,"hello");//第三个为hello
//q指向的是构造完的下一个
for(auto index = q;index != p; ++index)
{
cout << index << " ";
}
cout << endl;
while(q != p)
{
alloc.destroy(--q);//因为指向下一个所以先--, 我们只能对构造了的使用destroy
}
alloc.deallocate(p,n);
return 0;
}
拷贝和填充算法
/*
标准库为allocator定义了两个伴随算法, 可以在未初始化内存中创建对象
都定义在头文件: memory中
*/
uninitialized_copy(b,e,b2);//:迭代器b->e的范围元素拷贝到b2,b2内存需要足够大
uninitialized_copy_n(b,n,b2);//迭代器b以后n各元素拷贝到b2开始的内存
uninitialized_fill(b,e,t);//-----
uninitialized_fill(b,n,t);//----
//创建一个两倍vector<int> vec_int的控件将第一部分为vec_int,第二部分为填充值
vector<int> vec_int;
/*code:对vec_int赋值*/
allocator<int> alloc;
auto repoint = alloc.allocate(vec_int,size() * 2);
uninitialized_copy(vec_int.begin(),vec_int.end(),repoint);//返回值指向最后一个构造元素之后
uninitialized_fill(repoint,vec_int.size(),2);//填充2