动态数组
C++语言定义了第二种new表达式语法。能够分配并初始化一个对象数组。标准库中包括

一个名为allocator的类。同意我们将分配和初始化分离。

12.2.1 new和数组

void fun1()
{
int *pia=new int[2]; //pia指向第一个int
//方括号里的大小必须是整型,但不必是常量
typedef int arrT[42]; //arrT表示42个int的数组类型
int *p=new arrT; //分配一个42个int的数组;p指向第一个int
//实际上,编译的时候还是这种
int *p1=new int[42];
}

分配一个数组会得到一个元素类型的指针

因为分配的内存并非一个数组类型。因此不能对动态数组调用begin或end

也不能使用范围for语句来处理动态数组中的元素

初始化动态分配对象的数组

    int *pia=new int[10];           //10个未初始化的int
int *pia2=new int[10](); //10个值初始化为0的int
string *psa=new string[10]; //10个空string
string *psa2=new string[10](); //10个空string
//新标准中。我们还能够这样写
//10个int分别用列表中相应的值进行初始化
int *pia3=new int[10]{0,1,2,3,4,5,6,7,8,9};
//10个string类型的前面4个用给的值进行初始化。后面的进行值初始化
string *psa3=new string[10]{"a","an","the",string(3,'x')};

动态分配一个空数组是合法的

    size_t n=10,n2=0;
int *p=new int[n]; //分配数组保存元素
for(int* q=p ; q != p ; ++q)
{
/* 处理数组 */
}

若n为0,new会分配0个对象。

for循环中的条件会失败(p等于q+n,由于n为0)。

因此,循环体不会被运行

释放动态数组

    int *p=new int;
int *pa=new int[110];
//为了释放动态数组,我们使用一种特殊形式的delete——在指针前加上一方括号对
delete p; //p必须指向一个动态分配的对象或为空
delete [] pa; //pa必须指向一个动态分配的数组或为空 typedef int arrT[42]; //arrT是42个int的数组的类型别名
int *p1=new arrT; //分配一个42个int的数组;p指向第一个元素
delete [] p1; //方括号是必须的,由于我们当初分配的是一个动态数组

无论外面怎样,p指向的是一个对象数组的首元素,而不是一个类型为arrT的单一对象。

因此释放的时候必须加上方括号

智能指针和动态数组

    //up指向一个包括10个未初始化的int的数组
unique_ptr<int[]> up(new int[10]);
up.release(); //自己主动用delete[]销毁其指针
//当一个unique_ptr指向一个动态数组的时候我们能够用下标訪问数组中的元素
for(size_t i=0 ; i != 10 ; ++i)
up[i]=i; //为每一个元素赋予一个新值

和unique_ptr不同,shared_ptr不直接支持管理动态数组。

假设希望shared_ptr管理一个动态

    数组。那么就必须自己提供自定义的删除器

    //为了适应shared_ptr,必须提供自定义的删除器
shared_ptr<int> sp(new int[10], [](int *p){delete [] p;});
sp.reset(); //使用我们提供的lambda释放数组,它使用delete[]
//shared_ptr没有定义下标运算,也不支持下标运算
for(size_t i=0 ; i != 10 ; ++i)
*(sp.get()+i)=i; //使用get获取一个内置指针

12.23

/**
12.23
编写一个程序,链接两个字符串字面常量,将结果保存在一个动态分配的char数组中
重写这个程序。连接两个标准库string对象
*/
void fun6()
{
string s1="cutter",s2="_point";
unique_ptr<char[]> upc(new char[20]); for(size_t i=0 ; i != s1.size()+s2.size() ; ++i)
{
if(i < s1.size())
upc[i]=s1[i];
else
upc[i]=s2[i-s1.size()];
} for(int j=0 ; j != 20 ; ++j)
cout<<upc[j]; upc.release(); //自己主动用delete[]销毁其指针 }

12.2.2allocator类

普通情况下。将内存分配和对象构造结合在一起可能会导致不必要的浪费
    int n;
string *const p=new string[n]; //构造n个空string
string s;
string *q=p; //q指向第一个string
while(cin>>s && q != p+n)
*q++=s; //赋予*q一个新值
const size_t size=q-p; //记住我们读取了多少个string
//使用数组
delete [] p; //p指向一个数组;记得用delete[]来释放

可是。我们可能不须要n个string,少量string可能就足够了。

allocator类

    int n;
allocator<string> alloc; //可分配string的allocator对象
auto const p=alloc.allocate(n); //分配n各未初始化的string
/*
allocator分配微构造的内存
*/
auto q=p; //这里q指向和p一样
alloc.construct(q++); //*q为空字符串
alloc.construct(q++, 10, 'c'); //*q为cccccccccc
alloc.construct(q++, "hi"); //*q为hi!
//q指向最后构造的元素之后的位置
cout<<*p<<endl; //正确;使用string输出运算符
// cout<<*q<<endl; //灾难:q指向微构造的内存 while(q != p)
alloc.destroy(--q); //释放我们真正构造的string

所有代码展示

/**
* 功能:动态数组
* 时间:2014年7月9日10:05:01
* 作者:cutter_point
*/ #include<iostream>
#include<memory>
#include<string>
#include<vector> using namespace std; /**
C++语言定义了第二种new表达式语法,能够分配并初始化一个对象数组。 标准库中包括
一个名为allocator的类,同意我们将分配和初始化分离。
*/ /**
12.2.1 new和数组
*/
void fun1()
{
int *pia=new int[2]; //pia指向第一个int
//方括号里的大小必须是整型。但不必是常量
typedef int arrT[42]; //arrT表示42个int的数组类型
int *p=new arrT; //分配一个42个int的数组。p指向第一个int
//实际上,编译的时候还是这种
int *p1=new int[42];
} /**
分配一个数组会得到一个元素类型的指针
*/ /*
由于分配的内存并非一个数组类型,因此不能对动态数组调用begin或end
也不能使用范围for语句来处理动态数组中的元素
*/ /**
初始化动态分配对象的数组
*/
void fun2()
{
int *pia=new int[10]; //10个未初始化的int
int *pia2=new int[10](); //10个值初始化为0的int
string *psa=new string[10]; //10个空string
string *psa2=new string[10](); //10个空string
//新标准中。我们还能够这样写
//10个int分别用列表中相应的值进行初始化
int *pia3=new int[10]{0,1,2,3,4,5,6,7,8,9};
//10个string类型的前面4个用给的值进行初始化,后面的进行值初始化
string *psa3=new string[10]{"a","an","the",string(3,'x')};
} /**
动态分配一个空数组是合法的
*/
void fun3()
{
size_t n=10,n2=0;
int *p=new int[n]; //分配数组保存元素
for(int* q=p ; q != p ; ++q)
{
/* 处理数组 */
} /*
若n为0。new会分配0个对象。 for循环中的条件会失败(p等于q+n,由于n为0)。 因此,循环体不会被运行
*/
} /**
释放动态数组
*/
void fun4()
{
int *p=new int;
int *pa=new int[110];
//为了释放动态数组。我们使用一种特殊形式的delete——在指针前加上一方括号对
delete p; //p必须指向一个动态分配的对象或为空
delete [] pa; //pa必须指向一个动态分配的数组或为空 typedef int arrT[42]; //arrT是42个int的数组的类型别名
int *p1=new arrT; //分配一个42个int的数组;p指向第一个元素
delete [] p1; //方括号是必须的,由于我们当初分配的是一个动态数组 /*
无论外面怎样,p指向的是一个对象数组的首元素。而不是一个类型为arrT的单一对象。
因此释放的时候必须加上方括号
*/
} /**
智能指针和动态数组
*/
void fun5()
{
//up指向一个包括10个未初始化的int的数组
unique_ptr<int[]> up(new int[10]);
up.release(); //自己主动用delete[]销毁其指针
//当一个unique_ptr指向一个动态数组的时候我们能够用下标訪问数组中的元素
for(size_t i=0 ; i != 10 ; ++i)
up[i]=i; //为每一个元素赋予一个新值
/*
和unique_ptr不同,shared_ptr不直接支持管理动态数组。 假设希望shared_ptr管理一个动态
数组,那么就必须自己提供自定义的删除器
*/
//为了适应shared_ptr,必须提供自定义的删除器
shared_ptr<int> sp(new int[10], [](int *p){delete [] p;});
sp.reset(); //使用我们提供的lambda释放数组,它使用delete[]
//shared_ptr没有定义下标运算,也不支持下标运算
for(size_t i=0 ; i != 10 ; ++i)
*(sp.get()+i)=i; //使用get获取一个内置指针
} /**
12.23
编写一个程序,链接两个字符串字面常量,将结果保存在一个动态分配的char数组中
重写这个程序,连接两个标准库string对象
*/
void fun6()
{
string s1="cutter",s2="_point";
unique_ptr<char[]> upc(new char[20]); for(size_t i=0 ; i != s1.size()+s2.size() ; ++i)
{
if(i < s1.size())
upc[i]=s1[i];
else
upc[i]=s2[i-s1.size()];
} for(int j=0 ; j != 20 ; ++j)
cout<<upc[j]; upc.release(); //自己主动用delete[]销毁其指针 } /**
allocator类
*/
/*
普通情况下,将内存分配和对象构造结合在一起可能会导致不必要的浪费
*/
void fun7()
{
int n;
string *const p=new string[n]; //构造n个空string
string s;
string *q=p; //q指向第一个string
while(cin>>s && q != p+n)
*q++=s; //赋予*q一个新值
const size_t size=q-p; //记住我们读取了多少个string
//使用数组
delete [] p; //p指向一个数组;记得用delete[]来释放
/*
可是。我们可能不须要n个string。少量string可能就足够了。 */
} /*
allocator类
*/
void fun8()
{
int n;
allocator<string> alloc; //可分配string的allocator对象
auto const p=alloc.allocate(n); //分配n各未初始化的string
/*
allocator分配微构造的内存
*/
auto q=p; //这里q指向和p一样
alloc.construct(q++); //*q为空字符串
alloc.construct(q++, 10, 'c'); //*q为cccccccccc
alloc.construct(q++, "hi"); //*q为hi!
//q指向最后构造的元素之后的位置
cout<<*p<<endl; //正确;使用string输出运算符
// cout<<*q<<endl; //灾难:q指向微构造的内存 while(q != p)
alloc.destroy(--q); //释放我们真正构造的string
} int main()
{
fun6();
return 0;
}

PS:花了一早上,就搞了这么点东西,尽管中途歇息了一会。而且还玩了半个多小时的游戏,可是哥还是把这玩意所有搞完了,哈哈搞完了就能够好好玩一玩啦!!

【足迹C++primer】40、动态数组的更多相关文章

  1. C++ Primer 笔记——动态数组

    1.动态数组定义时也需要指明数组的大小,但是可以不是常量. int i; int arr[i]; // 错误,数组的大小必须为常量 int *p = new int[i]; // 正确,大小不必是常量 ...

  2. C++ Primer : 第十二章 : 动态内存之动态数组

    动态数组的分配和释放 new和数组 C++语言和标准库提供了一次分配一个对象数组的方法,定义了另一种new表达式语法.我们需要在类型名后跟一对方括号,在其中指明要分配的对象的数目. int* arr ...

  3. (待续)C#语言中的动态数组(ArrayList)模拟常用页面置换算法(FIFO、LRU、Optimal)

    目录 00 简介 01 算法概述 02 公用方法与变量解释 03 先进先出置换算法(FIFO) 04 最近最久未使用(LRU)算法 05 最佳置换算法(OPT) 00 简介 页面置换算法主要是记录内存 ...

  4. ALLOCATE语句分配FORTRAN动态数组方法(转自http://blog.csdn.net/zhuxianjianqi/article/details/8067174)

    数组的动态分配 a)    可分配数组 数组可以是静态的也可以是动态的.如果数组是静态的,则在编译时就被分配了固定的储存空间,并且直到程序退出时才被释放.程序运行时静态数组的大小不能改变.静态数组的缺 ...

  5. 线性表之顺序存储结构(C语言动态数组实现)

    线性表的定义:N个数据元素的有限序列 线性表从存储结构上分为:顺序存储结构(数组)和 链式存储结构(链表) 顺序存储结构:是用一段连续的内存空间存储表中的数据 L=(a1,a2,a3....an) 链 ...

  6. C语言 动态数组实现

    一.概述 C语言是不能直接定义动态数组的,数组必须在初始化时确定长度. 如果要在程序运行时才确定数组的长度,就需要在运行的时候,自己去向系统申请一块内存用动态内存分配实现动态数组. 二.动态内存分配函 ...

  7. fortran常用语句--读写带注释文档、动态数组等语法

    1.判断读取文档有多少行数据(文档最后的空行不计入其中): 首先在变量定义区域下方和执行语句前声明在程序中要被调用的GetFileN函数: external GetFileN 接下来在函数外部后边写上 ...

  8. 容器(vector)、数组、new创建的动态数组,你到底用哪一个(执行效率分析)

    1.问题的提出 在没有了解vector之前,动态数组一般都是又new创建的.在了解vector后发现vector竟是那样方便好用,但方便的同时却是以牺牲执行效率为代价的.网上对vector和array ...

  9. 分配一维动态数组or 二维动态数组的方法以及学习 new 方法or vector

    先来个开胃菜 // 使用new动态分配存储空间 #include<iostream> using std::cout; int main() { // 第1种方式 int *a=new i ...

随机推荐

  1. HOOK自绘原理 good

    做“HOOK文件打开/保存对话框”的过程中,我首先研究了界面库的相关知识.界面库一般都是由C/C++这种中低级语言编码,这是因为在Windows下的界面库实现技术大都以直接操作控制Windows的消息 ...

  2. JSTL解析——001

    JSTL 全称jsp standard tag library ,即jsp标准标签库. 是不是想问标签是什么东西? 标签就是jsp专门用于显示数据的,可重复利用的类库: 是不是想问标签由那些部分组成的 ...

  3. 纯后端尝试写一个前端slide插件

    概述 由于项目组前端人员缺失,又赶上需要在手机端做一个slide效果的页面,所以只能自己硬着头皮上了,写的很简单,请大家不要笑话,只是拿出来分享下,大家先看下完成后的效果,如下: 过程 看了效果图是不 ...

  4. OCA读书笔记(8) - 管理用户安全

    创建用户:create user +用户 default tablespace + 表空间名 identified + 验证方式 SQL> create user easthome profil ...

  5. [C#基础] 数据类型

    预定义类型 C#提供了16种预定义类型,其中包括13种简单类型和3种非简单类型. 预定义的简单类型包括以下3种: 11种数值类型 不同长度有符号和无符号的整数类型(8种) 浮点数类型float和dou ...

  6. php 写session

    function do_login(){ //获取用户名和密码信息,和数据库中比对 echo 111111111; dump($_POST); dump($_SESSION); echo 222222 ...

  7. Linux正则表达式grep与egrep

    grep -io "http:/=[A-Z0-9]\{16\}" ./wsxf.txt >wsxf_urls.txt Linux正则表达式grep与egrep 正则表达式:它 ...

  8. linux c socket 案源

    service结束 #include <sys/types.h> #include <sys/socket.h> #include <stdio.h> #inclu ...

  9. 斯坦福ML公开课笔记15—隐含语义索引、神秘值分解、独立成分分析

    斯坦福ML公开课笔记15 我们在上一篇笔记中讲到了PCA(主成分分析). PCA是一种直接的降维方法.通过求解特征值与特征向量,并选取特征值较大的一些特征向量来达到降维的效果. 本文继续PCA的话题, ...

  10. Windows - Windows的文件名的全路径(Fully Qualified File Name)的最大长度为260字节

    例如,你可以做以下实验来验证这个限制值: 在随意文件夹下新建一个文件夹. 在该新建文件夹下创建一个随意文件.使其名字长度不能再输入为止. 把该文件的全路径名copy到Microsoft Word中进行 ...