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

1.动态数组定义时也需要指明数组的大小,但是可以不是常量。

int i;
int arr[i];    // 错误,数组的大小必须为常量
int *p = new int[i];    // 正确,大小不必是常量

2.虽然我们通常称 new T[ ] 分配的内存为动态数组,但我们并未得到一个数组类型的对象,而是得到一个数组元素类型的指针。所以不能对动态数组调用begin或end,也不能用for语句来处理动态数组中的元素。

3.默认情况下,new分配的对象,不管是单个分配的还是数组中的,都是默认初始化的。我们可以用空括号对数组中元素进行值初始化,但是不能在括号中给出初始化器,这意味着不能用auto分配数组。

int *p = new int[3];    // 3个未初始化的int
int *p1 = new int[10]();    // 3个值初始化为0的int
int *p2 = new int[3]{ 1, 2, 3 };    // 列表初始化

4.虽然我们不能创建一个大小为0的静态数组,但是可以动态分配一个空数组,此时new返回一个合法的非空指针,此指针保证与new返回的其他任何指针都不相同。对于零长度的数组来说,此指针就像尾后指针一样,我们可以从此指针减去自身从而得到0.但是此指针不能解引用。

5.我们可以用delete [ ] 来释放数组,数组中的元素按逆序销毁,并释放对应的内存。

6.标准库提供了一个可以管理new分配数组的unique_ptr版本。

std::unique_ptr<int[]> p(new int[3]);
p[0] = 1;    // 为第一个元素赋值
p.release();    // 自动用delete[]销毁其指针

7.与unique_ptr不同,shared_ptr不直接支持管理动态数组,如果希望使用shared_ptr管理动态数组,必须提供自己定义的删除器。shared_ptr未定义下标运算符,而且智能指针类型不支持指针算术运算。因此,为了访问数组中的元素,必须用get获取一个内置指针,然后用它来访问数组元素。

std::shared_ptr<int> p(new int[10], [](int *p) {delete[] p; });    // 使用lambda释放数组
for (std::size_t i = 0; i != 10; ++i)
    *(p.get() + i) = i;    // 使用get获取一个内置指针

8.allocator是一个模板,它帮助我们将内存分配和对象构造分离开来,分配的内存是原始的,未构造的,当一个allocator对象分配内存时,会根据给定的对象类型来确定恰当的内存大小和对齐位置。

std::allocator<std::string> alloc;    // 可以分配string的allocator
auto const p = alloc.allocate(3);    // 分配n个未初始化的string
auto q = p;                        // q指向最后构造的元素之后的位置
alloc.construct(q++);            // *q为空字符串
alloc.construct(q++, 2, ‘c‘);    // *q为"cc"
alloc.construct(q++, "test");    // *q为"test"

std::cout << *p << std::endl;    // 正确,p指向第一个构造的元素
std::cout << *q << std::endl;    // 错误,q指向未构造的内存

while (q != p)
    alloc.destroy(--q);        // 执行了指向对象的析构函数 

// 元素被销毁后我们可以重新用这部分内存构造新对象,也可以将其归还给系统:
alloc.deallocate(p, 3);    // 注意这里的p不能为空,而且大小参数必须与分配时一样

9.标准库还为allocator类定义了两个伴随算法,可以在未初始化内存中创建对象。

时间: 2024-12-20 13:38:53

C++ Primer 笔记——动态数组的相关文章

[java笔记]动态数组

private int count;//计数器 private int ary[] = new int [3]; if(count >= ary.length){ //数组动态扩展 int newlen = (ary.length*3)/2 + 1; underwears = Arrays.copyOf(ary, newlen); } count++;

C++ Primer 笔记之数组

数组 数组是一种类似于标准库类型vector的数据结构,但是在性能和灵活性上又与vector有所不同.与vector 相似的地方是,数组也是存放类型相同的对象的容器,这些对象本身没有名字,需要通过其所在位置访问. 与vector不同的地方是,数组的大小确定不变,不能随意向数组中增加元素.因为数组的大小固定,因此 对某些特殊的应用来说程序的运行时性能较好,但是相应地损失了一些灵活性. Tip:如果不清楚元素的确切个数,请使用vector 定义和初始化内置数组 数组是一种复合类型.数组的声明形如a[

C++ primer 第十二章笔记之 动态数组

new与数组 为了让new分配一个对象数组,必须在类型名之后跟[].在其中指明分配的数目; int *pia = new int [ get_size() ]; //[]内必须为整型,但不必是常量; typedef int arrT[24]; int * p = new arrT; //分配一个24个int的数组,p指向第一个int; 初始化,C++11:可用花括号{}; 动态分配一个空数组是合法的; 释放动态数组: delete p; delete [] pa; 智能指针与动态数组: 标准库提

C++ Primer 学习笔记与思考_5 数组和动态数组易错点解读

1. 数组的定义 数组定义中的类型名可以是内置数据类型或者类类型:除了引用之外,数组元素的类型还可以是任意的复合类型.另外,非const变量以及要到运行阶段才知道其值的const变量都不能用于定义数组的维数. #include <iostream> #include <string> #include <cstring> #include <bitset> using namespace std; int main() { const int MAXN1 =

C++ Primer笔记8_动态内存_智能指针

1.动态内存 C++中,动态内存管理是通过一对运算符完成的:new和delete.C语言中通过malloc与free函数来实现先动态内存的分配与释放.C++中new与delete的实现其实会调用malloc与free. new分配: 分配变量空间: int *a = new int; // 不初始化 int *b = new int(10); //初始化为10 string *str = new string(10, ); 分配数组空间: int *arr = new int[10];//分配的

【足迹C++primer】40、动态数组

动态数组 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 /

C++自学笔记_数组和指针_《C++ Primer》

1.数据定义中的类型可以是内置数据类型或者类类型,除引用数据类型之外,数组元素的类型可是是任何数据类型.没有所有元素都是引用数据类型的数组. 2.数组的维数必须要用值大于等于1的表达式定义.此常量表达式只能包含整形字面值常量.枚举常量或者用常量表达式初始化的const对象,否则在编译阶段不知道数组的维数,对于一个非const对象,只有运行时才能获得它的值. const unsigned buf_size=512; int staff_size=27; char input_buffer[buf_

【C++ Primer每日一刷之八】之九 创建动态数组

4.3.1. 创建动态数组 数组类型的变量有三个重要的限制:[数组长度固定不变],[在编译时必须知道其长度],[数组只在定义它的块语句内存在]. 实际的程序往往不能忍受这样的限制--它们需要在运行时动态地分配数组. 虽然数组长度是固定的,但动态分配的数组不必在编译时知道其长度,可以(通常也是)在运行时才确定数组长度.与数组变量不同,动态分配的数组将一直存在,直到程序显式释放它为止.每一个程序在执行时都占用一块可用的内存空间,用于存放动态分配的对象,此内存空间称为程序的自由存储区或堆. C 语言程

重读C++ Primer笔记

C++ Primer 5E 有符号和无符号 无符号类型和有符号类型混合运算时,有符号数会被提升至无符号类型,如果其值为负责会产生错误. int main() { unsigned int u = 10; int i = -42; std::cout<<u+i<< std::endl; // 4294967264 if sizeof(int)==4 return 0; } 列表初始化 列表初始化过程不允许损失数据类型精度,所以下面代码中的两行无法通过编译 int main() { d