数组(array)是一种数据格式,可以存储多个同类型的值。每一个值都存储在一个独立的数组元素中,计算机在内存中依次存储数组的各个元素。ios
数组声明的三个特色:git
C++中能够经过修改简单变量的声明,添加中括号(其中包含元素数目)来完成数组声明。github
例如:编程
short days[24]; // 一天有24个小时
声明数组的的通常语法格式为:数组
// 数组类型 数组名字[数组的大小] int score[4]; // 四我的的分数,整型数组
数组的大小是指定元素的数目
,必须是整型常数或const值
,也能够是常量表达式(8*sizeof(int))安全
可使用其余的类型来建立(C语言使用术语:派生类型
)数据结构
数组的用途,能够单独访问数组元素,方法是:使用下标
或索引
对元素进行编号。从0开始编号
。函数
编译器不会检查下标是否有效,因此要注意下标合法性,避免程序异常问题。
C++使用索引的方括号表示法来指定数组元素。工具
1.只有在定义数组时才能初始化,此后不能使用,也不能将一个数值赋给另外一个数组。学习
2.初始化数组时,提供的值少于数组的元素数目。
3.若是只对数组的一部分进行初始化,则编译器把其余元素设置为0。
4.若是初始化为{1}
而不是{0}
,则第一个元素被设置为1,其余元素都被设置为0.
5.若是初始化数组方括号内([])
为空,C++编译器将计算元素个数
。 例如:short things[] = {1,3,5,7};
C++11将使用大括号的初始化(列表初始化)
做为一种通用的初始化方式,可用于全部类型。
在C++中列表初始化就增长了一些功能:
等号(=)
double earnings[4] {1.2e4,1.6e4,1.1e4,1.7e4};
unsigned int const[10] = {}; float balances[100] {};
long num[] = {25,92,3.0}; // 浮点数转换为整型是缩窄操做
例子:
#include<iostream> using namespace std; int main() { // 建立一个名字为yams的数组,包含了3个元素,编号是0~2. int yams[3]; yams[0] = 7; yams[1] = 8; yams[2] = 6; // 使用逗号分隔的值列表(初始化列表),而后用花括号括起来便可。 // 列表中的空格是可选的,若是没有初始化函数中定义的数组,其元素值也是不肯定。 int yamcosts[3] = {1,2,3}; cout<<"yams 数组是:"<<yams[0]+yams[1]+yams[2]<<endl; cout<<"yams[1] = "<<yams[1]<<endl; int total = yams[0] * yamcosts[0] + yams[1] * yamcosts[1]; total = total + yams[2] * yamcosts[2]; cout<<"total yam = "<<total<<endl; // sizeof运算符返回类型或数据对象的长度(单位为字节)。 // 若是将sizeof运算符用于数组名,获得的是整个数组的字节数。 // 若是sizeof用于数组元素,获得的是元素的长度(单位为字节)。 cout<<"\n yams数组的大小 = "<<sizeof(yams)<<" Bytes.\n"; cout<<"一个元素的大小 = "<<sizeof(yams[0])<<" Bytes.\n"; return 0; }
字符串是存储在内存的连续字节中的一系列字符。
C-风格字符串(C-style String)
以空字符(\0,ASCII码对应为0)来标记字符串的结尾。
存储在连续字节
中的一系列字符意味着能够将字符串
存储在char数组
中。其中每一个字符都位于本身的数组元素中。
使用引号
括起来的字符串,这种字符串叫 字符串常量(String constant)
或 字符串字面值(string literal)
。
字符串常量(使用双引号)不能与字符常量(使用单引号)互换。
例如:
char name[] = "Soler";
字符串结尾的空字符
,不用直接显式包括
,机器在键盘输入,将字符串读入到char类型
中,会在结尾自动加上空字符
。
⚠️注意:肯定了存储字符串所需的最短数组时,不要忘记把结尾的空字符
包括在内。
方法:直接两个引号括起来的字符串合并为一个。任何两个由空白(空格、制表符和换行符)
分隔的字符串常量都将自动拼接成一个。
cout<<"My name is " "Soler HO.\n"
将字符串存储到数组的经常使用方法:
#include <iostream> #include <cstring> /*提供strlen()函数*/ using namespace std; const int Size = 15; int main() { char name1[Size]; char name2[Size] = "C++owboy"; // 字符串的拼接 cout<<"Howdy!I'm "<< name2; cout<<"!,What's your name?\n"; cin>>name1; cout<<"Well, "<<name1<<",your name has : "<<strlen(name1)<<" letters and is stored!\n" ; cout<<"In an array of "<<sizeof(name1)<<" Bytes\n"; cout<<"Your iniatial is "<<name1[0]<<".\n"; // name1数组中的第一个元素 name2[3] = '\0'; cout<<"Here are the first 3 characters of my name:"<<name2<<endl; return 0; }
strlen() 函数
和 sizeof()运算符
的区别
strlen()
函数
存储在数组中的字符串的长度
,而~~不是数组自己的长度~~
。可见的字符
,而sizeof()
运算符
变量
或数据类型
的字节大小
。类、结构、共用体和其余用户自定义数据类型
的大小。解决没有逐行读取输入的缺陷。
istream中提供了面向行的类成员函数:getline()
和 get()
函数
getline()
使用经过回车键输入的换行符来肯定输入结尾。使用 cin.getline()
。
函数有两个参数:
数组名称
。空字符(\0)
)。格式:
cin.getline(name,ArSize);
get()
与getline()
函数相似,接受的参数相同
,解释参数的方式也相同,并读到行尾
。
区别:get()
读取并丢弃
换行符,将其留在输入队列中。
格式:
cin.get(name,ArSize);
get() 将两个类成员函数拼接(合并):
cin.get(name,ArSize).get();
⚠️注意:get() 函数读取空行后设置会失效,输入会被阻断。可用以下恢复:
cin.clear();
混合输入数字和面向行的字符串会致使的问题:没法输入地址。
解决方法:直接使用get()进行读取以前丢弃换行符。
string类
位于名称空间std
中,因此须要提供using指令
或者是直接使用std::string
进行引用。
要使用string类
,必须在程序中包含头文件string
中。
string类定义隐藏了字符串的数组性质。
使用string对象的方式和使用字符数组相同。
C-风格字符串
来初始化string对象中。cin来将键盘输入
存储到string对象中。cout
来显示string对象。数组表示方法
来访问存储在string1对象中的字符。赋值 —— 不能将一个数组赋给另外一个数组,但能够将一个string对象赋另外一个string对象。
char char01[20]; // 建立一个空列表 char char02[20] = "Jason"; // 建立一个初始化数组 string str01; // 建立一个空的string对象 string str02 = "Soler Ho"; // 建立一个初始化的string对象 char01 = char01; // 不可执行,一个数组不能赋值给另外一个数组 str01 = str02; // 可执行,可将一个string对象赋给另外一个string对象。
string类简化字符串合并操做。
运算符 +
将两个string对象合并起来。string str01; string str02 = "Soler Ho"; string = str01 + str02;
运算符 +=
将字符串附加
到string对象的末尾
。string str01; string str02 = "Soler Ho"; str01 += str02;
结构是用户定义
的类型,而结构声明定义了类型的数据属性
。
定义类型以后,就直接建立类型的变量。
结构比数组灵活,同一个结构中能够存储多种类型的数据。
定义结构描述 —— 描述并标记可以存储在结构中的各类数据类型
按描述建立结构变量(结构数据对象)。
struct(关键字) 类型名(标记成为新类型的名称) { 结构成员1; 结构成员2; 结构成员3; };//(结束结构声明)
对于结构中的成员,使用成员运算符(.)
来进行访问各个成员。
等号(=)无关紧要
。infor Soler_infor {"Soler HO",55,168}; // 在C++11中,= 号能够省略
infor Soler_infor {};
✅ 小Tips:C++容许在声明结构变量时省略关键字struct。
成员赋值(memberwise assignment):可使用赋值运算符(=)
将结构赋另外一个同类型的结构。这样结构中的每一个成员都将被设置为另外一个结构中相应成员的值。即便成员是数组。这种方式就是成员赋值
。
共用体(union),也叫作联合(union)
。一种 构造数据类型
。
关键字:union
联合(union):将不一样类型的数据
在一块儿共同占用同一段内存
存储不一样的数据类型,但只能同时存储其中的一种类型
示例:
union sample { int int_val; long long_val; double double_val; };
同时存储int、long和double
。只能存储int、long和double
三种。匿名共用体(anonymous union)没有名称
,其成员将成为位于相同地址
处的变量。
C++的enum工具提供了另外一种建立符号常量
的方式,能够代替const,容许定义新类型,但必须有严格限制。
使用enum的语法格式与结构的使用相似。
enum color{red,orange,yellow,green,blue,voilet};
enum week{Monday = 1,Tuesday = 2;Wednesday = 3;Thursday = 4};
指定的值必须是整数
。也能够只显示定义其中一些枚举量的值
。
若是第一个变量未初始化,默认为0。后面没有被初始化的枚举量的值将比其前面的枚举量大1。也能够建立多个值相同的枚举量。
enum {zero,null = 0,numero_one,one = 1};
每一个枚举都有取值范围的上限,经过强制类型转换,能够将取值范围中的任何整数值赋给枚举常量,即便这个值不是枚举值。
对于选择使用多少空间来存储枚举由编译器
决定。
对于地址显示结果是十六进制表示法
,由于都是经常描述内存的表示法
。
指针与C++基本原理
面向对象编程和传统的过程性编程的区别,OOP强调的是运行阶段(而不是编译阶段)进行决策。
指针用于存储值的地址。指针名表示的是地址。
*运算符
称为间接值或解除引用运算符,将其应用于指针,获得该地址处存储的值。
指针的声明必须指定指向的数据的类型
。
int *p_updates;
*p_updates
的类型是int
,因此*运算符
被用于指针
,因此p_updates变量必须是指针。
运算符*两边的空格
是可选的。
int *ptr; /*该状况强调:*ptr是一个int类型的值。*/ int* ptr; /*该状况强调:int* 是一种类型,指向int的指针。*/
在C++中,int*
是一种复合类型,是指向int的指针
。
double *tax_ptr;
在C++建立指针时,计算机将分配用来存储地址的内存
,可是不会分配用来存储指针所指向的数据的内存。
⚠️注意:必定要在对指针应用解除引用运算符(*)
以前,将指针初始化为一个肯定
的、适当的地址
。
整数能够加减乘除等运算,而指针
描述的是位置
。
C++语言数字不能做为地址使用,若是要把数字当地址来使用,应经过强制类型转换
将数字转换为适当的地址类型。
new分配
和delete释放
内存指针在运行阶段
分配未命名的内存以存储值。而后使用内存来访问内存。
C语言中,使用 库函数malloc()来分配内存。C++中使用 ———— new运算符。
须要内存时,直接使用new来请求,这是内存管理数据包的一个方面。
若是使用了delete运算符
,使得在使用完内存后,可以将其归还给内存池
,这是有效使用内存的关键。
使用delete时,后面要加上指向内存块的指针。
int * ps = new int; // 使用new进行内存分配 ... delete ps; // 使用delete进行内存的释放
1.使用delete释放ps的内存,可是不会删除指针ps自己。
2.只能用delete
来释放使用new分配的内存
,可是若是是空的指针
使用delete是安全的。
使用delete的关键:用于new分配的内存
。不是要使用于new的指针,而是用于new的地址
。
❌警告:不能建立两个指向同一个内存块的指针。会增长错误地删除同一个内存块两次的可能性。
C++中,建立动态数组,只须要将数组的元素类型
和元素数目
告诉new便可。必须在类型名
后面加上方括号
,其中包含了元素数目。
通用格式:
Type_name *pointer_name = new Type_name[num_element]; //例子 int * psome =new int[10]; // 建立10个int元素的数组
new运算符会返回第一个元素的地址
若是使用完new分配的内存,使用delete进行内存的释放。
delete [] psome; // 进行内存的释放
delete和指针直接的方括号告诉程序,应释放整个数组
,不只仅是指针指向的元素。
delete中的方括号的有无
取决于使用new时的方括号有无
。
对于指针数组的使用,直接能够按照普通数组的使用便可。
new[]
为数组
分配内存时,则应使用delete[]
来释放。实体
分配内存,则应使用delete(没有方括号)
来释放。指针和数组基本等价的缘由:指针算术(pointer arithmetic)
和C++ 内部处理数组的方式
。
- 对
整数变量
+ 1,其值
增长1- 对
指针变量
+ 1,增长的量等于它指向的类型的字节数
。
获取数组地址的两种方式
double * pw = wages; // 数组名 = 地址 ;将pw声明为指向double类型的指针。而后将其初始化为wages - - - wages数组中第一个元素的地址。 short * ps = &wages[0]; // 使用地址操做;使用地址运算符来将ps指针初始化为stacks数组的第一个元素。
要声明指向特定类型的指针,语法格式:
TypeName *pointerName; // 例子 double * pn; // pn 指向一个double类型 char * ps; // ps 指向一个char类型
将内存地址赋给指针。能够对变量名应用 & 运算符
,来得到被变量名的内存地址
,new运算符返回未命名的内存的地址。
示例:
double * pn; // pn 指向一个double类型 double * pa; // pa 指向一个double类型 char * pc; // pc 指向一个char类型 double bubble = 3.2; pn = &bubble; // 把bubble的地址赋值给 pn pc = new char; // 新建char地址并分配给pc
对指针解除引用意味着得到指针指向的值
。
引用
或间接值运算符(*)
来解除引用。cout<<*pn; *pc = 's';
数组表示法
。多数状况下,C++将数组名
视为数组的第一个元素的地址
。
int tacos[10]; // 此时的tacos一样也是&tacos[0]
C++中容许指针和整数相加
。加1 的结果等于原来的地址值
加上指向的对象占用的总字节数
。
也能够将一个指针减去另外一个指针,得到两个指针的差。获得一个整数,仅当两个指针指向同一个数组(也能够指向超出结尾的一个位置)时,这种状况会获得两个元素的间隔。
使用数组声明来建立数组时,将采用静态联编
,即数组长度在编译
时设置。
int tacos[10] // 静态联编
使用new[]运算符
建立数组时,将采用动态联编(动态数组)
,即将在运行时为数组分配空间,其长度为运行时设置。
使用这类数组后,要使用
delete[]
释放所占用的内存。
使用方括号数组表示法
等同于对指针解除引用
。
数组名和指针变量也是同样。因此对于指针和数组名,既可使用指针表示法
,也可使用数组表示法
。
int * pt = new int [10]; *pt = 5; pt[0] = 6; pt[9] = 5; int coats[10]; *(coats + 4) = 12;
数组名是第一个元素地址
。
若是给cout提供一个字符的地址,则它将从该字符开始打印,直到遇到空字符为止。
在cout和多数C++表达式中,char数组名
、char指针
以及用引号括起来的字符串常量
都被解释为字符串第一个字符的地址
。
不要使用字符串常量或未被初始化的指针来接收输入。
在字符串读入程序时,应使用已分配的内存地址。该地址不是数组名,也可使用new初始化过的指针。
strcpy()
接受两个参数,第一个:目标地址
,第二个:要复制的字符串的地址
。
要肯定目标空间有足够的空间来存储副本。
对于在指定结构成员时,句点运算符
和箭头运算符
的选择时:
结构名
,则使用句点运算符(.)
。指向结构的指针
,则使用箭头运算符(->)
。把new用于结构的两个步骤
要建立结构,须要同时使用结构类型和new。
自动变量
。
只在特定函数被执行时存在。
自动变量时一个局部变量
,做用域为包含它的代码块
。一般存储在栈
中,遵循后进先出(LIFO)
。
静态存储
整个程序执行期间都存在的存储方式(存在于程序的整个生命周期
)。
动态存储
内存池(自由存储空间或堆)用于静态变量和自动变量,且内存是分开的。
线程存储(C++11特性)
模板类vector
和array
是数组的替代品。
模板类vector
相似于string
类,也是一种动态数组
。
vector对象
包含在vector头文件
中。using编译指令
、using声明
或std::vector
。语法
来指出它存储的数据类型
。元素数
。位于名称空间std
中,与数组同样,array对象的长度固定
,也使用栈(静态内存分配)
,而不是自由存储区
。
头文件 array。
不管是数组、vector对象仍是array对象,均可使用标准数组表示法
来访问各个元素。
从地址
可知,array对象和数组存储在相同的内存区域(即栈)
中,vector对象存储在自由存储区域或堆
中。
能够将一个array对象赋给另外一个array对象,对于数组,必须逐个
元素复制
数据。
Github地址:https://github.com/SolerHo/cpp-Primer-Plus-6e-Notes/blob/master/Chapter04/README.md
第四章 学习笔记完毕,若有大佬在文中发现错误,请指出,谢谢