C++ Primer 笔记之数组

数组

数组是一种类似于标准库类型vector的数据结构,但是在性能和灵活性上又与vector有所不同。与vector

相似的地方是,数组也是存放类型相同的对象的容器,这些对象本身没有名字,需要通过其所在位置访问。

与vector不同的地方是,数组的大小确定不变,不能随意向数组中增加元素。因为数组的大小固定,因此

对某些特殊的应用来说程序的运行时性能较好,但是相应地损失了一些灵活性。

Tip:如果不清楚元素的确切个数,请使用vector

定义和初始化内置数组

数组是一种复合类型。数组的声明形如a[d],其中a是数组的名字,d是数组的维度。维度说明了数组中

元素的个数,因此必须大于0.数组中元素的个数也属于数组类型的一部分,编译的时候维度应该是已知的。

也就是说,维度必须是一个常量表达式:

unsigned cnt = 42; //不是常量表达式

constexpr unsigned sz = 42; //常量表达式

int arr[10]; //含有10个整数的数组

int *parr[sz]; //含有42个整型指针的数组

string bad[cnt]; //错误:cnt不是常量表达式

string strs[get_size()]; //当get_size是constexpr时正确;否则错误

默认情况下。数组的元素被默认初始化

WARNNING: 和内置类型的变量一样,如果在函数内部定义了某种内置类型的数组,那么默认

初始化会令数组含有未定义的值

定义数组的时候必须指定数组的类型,不允许用auto关键字由初始值列表推断类型。另外

和vector一样,数组的元素应为对象,因此不存在引用的数组。

不允许拷贝和赋值

不能将数组的内容拷贝给其他数组作为其初始值,也不能用数组为其他数组赋值:

int a[] = {0,1,2}; //含有3个整数的数组

int a2[] = a; //错误:不允许使用一个数组初始化另一个数组

a2 = a; //错误:不能把一个数组直接赋值给另外一个数组

WARNNING:一些编译器支持数组的赋值,这就是所谓的编译器扩展(compiler extension).但一般

来说,最好避免使用非标准特性,因为含有非标准特性的程序很可能在其他编译器上无法正常工作。

理解复杂的数组声明

和vector一样,数组能存放大多数类型的对象。例如,可以定义一个存放指针的数组。又因为

数组本身就是对象,所以允许定义数组的指针及数组的引用。在这几种情况中,定义存放指针的数组

比较简单和直接,但是定义数组的指针或数组的引用就稍微复杂一点了:

int *ptrs[10]; //ptrs是含有10个整型指针的数组

int &refs[10] = /* ? */; //错误:不存在引用的数组

int (*Parray)[10] = &arr; //Parray指向一个含有10个整数的数组

int (&array)[10] = arr; //arrRef引用一个含有10个整数的数组

int *(&arr)[10] = ptrs; //array是数组的引用,该数组含有10个指针

在一些情况下数组的操作实际上是指针的操作,这一结论有很多隐含的意思,其中一层意思是当使用

数组作为一个auto变量的初始值时,推断得到的类型是指针而非数组:

int ia[] = {0,1,2,3,4,5,6,7,8,9}; //ia是一个含有10个整数的数组

auto ia2(ia); //ia2是一个整型指针,指向ia的第一个元素

ia2 = 42; //错误:ia2是一个指针,不能使用int值给指针赋值

尽管ia是由10个整数构成的数组,但当使用ia作为初始值时,编译器实际运行的初始化过程类似于下面

的形式:

auto ia2(&ia[0]); //显然ia2的类型是int*

必须指出的是,当使用decltype关键字时上述转换不会发生,decltype(ia)返回的类型是由10个整数构成

的数组:

//ia3是一个含有10个整数的数组

decltype(ia) ia3 = {0,1,2,3,4,5,6,7,8,9};

ia3 = p; //错误:不能使用整型指针给数组赋值

ia3[4] = i; //正确:把i的值赋给ia3的一个元素。

时间: 2024-12-11 05:02:47

C++ Primer 笔记之数组的相关文章

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

1.动态数组定义时也需要指明数组的大小,但是可以不是常量. int i; int arr[i]; // 错误,数组的大小必须为常量 int *p = new int[i]; // 正确,大小不必是常量 2.虽然我们通常称 new T[ ] 分配的内存为动态数组,但我们并未得到一个数组类型的对象,而是得到一个数组元素类型的指针.所以不能对动态数组调用begin或end,也不能用for语句来处理动态数组中的元素. 3.默认情况下,new分配的对象,不管是单个分配的还是数组中的,都是默认初始化的.我们

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笔记

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

C++ Primer笔记7_STL之关联容器

关联容器 与顺序容器不同,关联容器的元素是按关键字来访问和保存的.而顺序容器中的元素是按他们在容器中的位置来顺序保存的. 关联容器最常见的是map.set.multimap.multiset map的元素以键-值[key-value]对的形式组织:键用作元素在map中的索引,而值则表示所存储和读取的数据. set仅包含一个键,并有效的支持关于某个键是否存在的查询. pair类型 首先介绍下pair,pair定义在utility头文件中,一个pair保存两个数据成员,类似容器,pair是一个用来生

C++ Primer笔记5_STL之顺序容器

1.STL(Standard Template Library) 标准模板库.从根本上说,STL是一些"容器"的集合,这些"容器"有list, vector,set,map等,STL也是算法和其它一些组件的集合.这里的"容器"和算法的集合指的是世界上很多聪明人很多年的杰作.每一个C++程序员都应该好好学习STL.大体上包括container(容器).algorithm(算法)和iterator(迭代器),容器和算法通过迭代器可以进行无缝连接. 2

[Java基础笔记]数组

Java基础笔记 定义数组: int[] numbers = new int[100]; //方法一 double[] num = new double[10]; int[][] a = new int[2][5]; 通过new创建的数组,元素默认值为0(0.0) int[] scores = {5,4,33,12,46}; //方法二 int[][] a = { //位数不足,自动补0 {5,3,2,1,6}, {10,12,14,15}, }; 数组特性:存储的都是同类型数据:长度定义后不可

C++ Primer笔记12_运算符重载_递增递减运算符_成员访问运算符

1.递增递减运算符 C++语言并不要求递增递减运算符必须是类的成员.但是因为他们改变的正好是所操作对象的状态,所以建议设定为成员函数. 对于递增与递减运算符来说,有前置与后置两个版本,因此,我们应该为类定义两个版本的递增与递减运算符. 问题来了,程序是如何区分前置和后置呢?因为都是++和-- 为了解决这个问题,后置版本的递增递减运算符接受一个额外的(不被使用)int类型的形参.当我们使用后置运算符时,编译器为这个形参提供一个值为0的实参.这个形参唯一的作用就是区分前置和后置运算符函数. 因为不会

C++ Primer笔记2_四种类型转换_异常机制

1.类型转换 命名的强制类型转换: 有static_cast.dynamic_cast.const_cast.reinterpret_cast static_cast: 编译器隐式执行的任何类型转换都可以由static_cast完成 当一个较大的算术类型赋值给较小的类型时,可以用static_cast进行强制转换. 可以将void*指针转换为某一类型的指针 可以将基类指针强制转换为派生类指针,但是不安全. 无法将const转化为nonconst,这个只有const_cast才可以办得到 举例:

C++ Primer笔记6_STL之泛型算法

1.泛型算法: 大多数算法定义在头文件algorithm中,标准库还在头文件numeric中定义了一组数值泛型算法 只读算法: 举例: find函数用于找出容器中一个特定的值,有三个参数 int val = 10;//val为我们需要查找的值 auto result = find(vec.begin(), vec.end(), val): cout << "The value "<< val << (result == vec.end() ? &qu