C++ Primer Plus第四章

本文为读书笔记,有自己的理解,如果有错误地方,请指正

4.1数组

C++里的数组是一种数据格式,可以存储多个同类型的值,比如int,float,short

数组声明应指出以下三个点:

1.数组在每个元素中的值得类型

2.数组名字

3.数组中的元素数

这里跟python不一样的地方就是python很随意,C++需要额外声明元素的值的类型和元素数量

举个栗子:

short months[12];
/* 通用格式: typeName arrayName[arratSize] */

上边的通用格式很明显啦

注意,编译器不会检查使用的数组下标是否有效,如果将一个赋值给不存在的元素,编译器不会报错(牛批),但是程序运行可能引发错误,这个必须使用有效的下标值(这个记住啊,别数组有10个数据,来个超出下标的赋值,当然它的赋值规则跟Python一样样了,months[0]=1这种)

4.1.2 数组初始化

int months[3]={1,2,3};

C++允许对数组声明的时候初始化,用花括号括起来,上图那样,

规则:

1.只有定义数组的时候才可以初始化

2.初始化数组的时候提供值可以少于数组中的元素数目,当然,其余没有提供值的元素,全部初始化为o,当然下边是快速初始化0的方法,只给数组下标0位置提供值0

int months[3]={0};

3.如果初始化数组时,方括号([])没有指定数组元素的数量,这个就由编译器计算元素数量了,下边这个实例,编译器自动算出,数组含有四个元素

int months[]={1,2,3,4};

注意,这样很不好,很糟糕,因为万一提供值少了,那么数组会少计算值数量,这样会造成偏差,你以为四个值,但是忘了一个,数组包含三个,后续有隐患

C++11 新特性

可以省略“=”

int months[2]{1,2,3};

大括号不包含任何东西,代表初始化全部为0

int months[3]{};

4.2 字符串

字符串有通常的两种

char dog[3]={"b","a","k","l"};
char dog[3]={"bakl"};

我觉得用第一种丧心病狂,而且第一种遇到空格字符就会停止,第二种就没问题了

4.2.1 拼接字符串常量

cout <<"i like" "you.\n";
cout <<"i like you. \n";
cout <<"i"
"like you.\n;

上边三种都可以,不会增加拼接的字符,拼接后边的字符会紧跟着前边的字符

4.2.4 读取一行字符串输入

cin.getline(name,10)

这个函数是读取整行,然后不超过9个字符,自动在结尾增加空字符,读取指定数目字符或者换行符停止读取,但不保存换行符,存储字符串时候回使用空字符来替换换行符

cin.get()

第一种类似getling(),但是不再读取并丢弃换行符,而是加入到输入队列,如果两次调用get(),第二次调用看到的字符就是换行符,所以就会停止,因此可以使用下边的方法

cin.get(name,AirSize);
cin.get();
cin.get(name,AirSize);

还有这样也可以

cin.get(name,AirSize).get();

空行和其他问题:

getline()或者get()读取空行时,会发生什么问题,接下来的输入会被阻断,可以通过cin.clear()来恢复

如果混合输入的话,只能调用拼接

(cin >> year).get(); // or (cin >> year).get(ch);

4.3 String类

这个也是个字符串处理的方法,String类位于std命名空间中,可以初始化,可以cin输入,可以cout显示,可以用数组表示方法显示string对象

区别就是一个是字符数组一个是简单变量的声明,也可以用运算符"+"来拼接

4.3.3 string类的其他操作

strcpy(charr1,charr2); // copy charr2 to charr1

strcat(charr1,charr2); // append charr2 to charr1

当然可以计算字符的长度,

数组类的:

int len1 = strlen(charr1);

使用string可以用这个:

int len1 = str1.size()

4.4 结构

数组只能存一致的数据,比如20个Int,所以出现了结构,满足用户更多数据存储的要求,使用关键字struct表明

struct inflatable
{
    char name[20];
    float volume;
    double price
};

这个可以存储不同的数据(python貌似数组可以胡乱存储。。。。。)

然后就能声明这种结构的变量了

inflatbale pao = 
{
    "Glorious Gloria",
    1.88,
    29.9
};

这有点像面向对象了。。。。输出数据都是pao.name 输出是"Glorious Gloria"

然后就是外部和main()内声明的问题了,跟变量一样,自行脑补

4.4.6 共用体

union one4all
{
    int int_val;
    long long_val;
    double double_val;
};

这个其实就是共用体不像结构可以存储多个数据类型,每次只能存储一种,有时候是int,有时候是long,有时候是double,数据项使用两种或者多种的时候,可以节省空间,通常用来节省内存的,因为共用体是匿名的。因此两个成员的地址想用,不需要中间标识符id_val,由程序员负责哪个是活动的

4.6 枚举

enum spectrum{red,orange,green};

就是强制性增加了规定的赋值,超出就不可以赋值

如果不创建枚举类型变量,可以忽略枚举类型的名称

枚举变量可以直接输出,但不能直接输入。如:cout >> color3; //非法
不能直接将常量赋给枚举变量。如: color1=1; //非法
不同类型的枚举变量之间不能相互赋值。如: color1=color3; //非法
枚举变量的输入输出一般都采用switch语句将其转换为字符或字符串;枚举类型数据的其他处理也往往应用switch语句,以保证程序的合法性和可读性。
4.7 指针和自由存储空间

首先说一下计算机程序在存储数据时必须跟踪的3种基本属性

1.信息存储在何处

2.存储的值为多少

3.存储的信息是什么类型

指针存储的就是值的地址,可以使用地址运算符(&),比如一个值是home,那么&home就是他的地址

指针的名表示的是地址,运算符被称为间接值或者解除引用运算符,可以的到这个地址储存的值,假如name是一个指针,那么name表示的就是存储在该地址的值

4.7.1 声明和初始化指针

int* p1, p2 这个还是要强调,这个表示声明一个指针和一个int变量,每个指针变量名,都需要一个*

如下,简单的初始化指针为一个地址

int higgens = 5

int * pt =  &higgens

注意:

long * fellow;
* fellow = 2332233;

上边这种没有将地址赋值给fellow这个就不知道将2332233放到了哪里,

long fellow = 2332233;

long * fe = &fellow;

警告:所以,一定要在对指针应用解除引用运算符(*)之前,将指针初始化一个确定的,适当的地址,这是对于指针使用的金科玉律。

4.7.4 使用new来分配内存

int * pn = new int;

new运算符根据类型来确定需要多少字节的内存,然后找到内存返回地址

通用格式如下:

typeName * pointer_name = new typeName;
int nights = 1001;
int * pt = new int;
*pt = 1001;
double * pd = new double;
*pd = 10000001.0;

但是要知道,new分配内存从堆或自由存储区分配的内存,变量的值存储在栈的内存区域中

4.7.5 使用delete释放内存

使用new来使用内存,当然可以用delete来释放内存

int * ps = new int;
...
delete ps;

如上就是释放了ps的内存

但是不能释放已经释放的内存块,以及声明变量所获得的内存

如下:

int * ps = new int;
delete ps;
delete ps; // not ok now
int jugs = 5;
int * pi = &jugs;
delete pi; // not allow, memory not allocated by new

4.7.6使用new来创建动态数组

int * pt = new int [10];
delete [] pt

但是*pt是指向该数组的第一个元素值

但是仍然可以使用pt[1],pt[0]这种获取数组的值

使用new,delete遵守的规则:

1.不要使用delete来释放不是new 分配的内存

2.不要使用delete来释放同一个内存块两次

3.如果使用new[]为数组分配内存,应该使用delete []来释放

4.如果使用new为一个实体分配内存,应该使用delete(没有方括号)来释放

5.对于空指针应用delete是安全的

4.8.4 使用new创建动态结构

inflatable * ps = new inflatable;
这种只知道地址的不能使用句点运算符,要使用箭头运算符(->)

如果结构标识符是结构名,使用句点运算符,如果是指向结构的指针,使用箭头运算符

4.10 数组的替代品

array 写一下这个吧

array<typeName, n_lem> arr;

array<double, 4> a3 = {3.14, 2.72, 1.62, 1.41};

总结:

数组、结构和指针是C++的三种复合类型,数组可以在一个数据对象中存储多个同种类型的值,通过使用索引和下标,可以访问数组中各个元素

结构可以将多个不同类型的值存储在同一个数据对象中,可以使用成员关系运算符(.)来访问其中的成员,使用结构的第一步就是创建结构模板,它定义结构存储了那些成员,模板的名称将成为新类型的标识符,然后就可以声明这种类型的结构变量

共用体可以存储一个值,但是值可以是不同的类型,成员名指出了使用的模式

指针是呗设计用来存储地址的变量,我们说,指针指向它的存储地址,指针声明指出了指针指向的对象的类型,对指针应用接触引用运算符,将得到指针指向的位置中的值

字符串是以空字符为结尾的一系列字符,字符串可以用引号括起的字符串常量表示,其中隐式包含了结尾的空字符,可以将字符串存储在char数组中,可以用被初始化为指向字符串char的指针表示字符串,函数strlen()返回字符串的长度,其中不包括空字符,函数strpy()将字符串从一个位置复制到另一个位置,在使用这些函数时,应当包括头文件csting和string.h

头文件string支持的C++ string类提供了另一种对用户有好的字符串处理方法,string对象将根据要存储的字符串自动调整其大小,用户可以使用赋值运算符来复制字符串

new运算符允许在程序运行时为数据对象请求内存,该运算符返回获得内存的地址,可以将这个地址赋给一个指针,程序将只能使用该指针来访问这块内存,如果数据对象是简单变量,则可以使用接触引用运算符(*)来获得其值,如果数据对象是数组,则可以像使用数组名那样使用指针来访问元素,如果数据对象是结构,则可以使用指针解除引用运算符(->)来访问其成员

指针和数组紧密相关,如果ar是数组名,则表达式ar[i]被解释为*(ar+i),其中数组名被解释为数组第一个元素的地址,这样,数组名的作用和指针相同,反过来,可以使用数组表示法,通过指针名来访问new分配的数组中的元素

运算符new和delete允许显示控制何时给数据对象分配内存,何时将内存归还给内存池,自动变量是在函数中声明的变量,而静态变量是在函数外部或者使用关键字static声明的变量,这两种变量都不太灵活,自动变量在程序执行到其所属的代码块(通常是函数定义)时产生,在离开该代码块时终止,静态变量在整个程序周期内都存在,C++98新增的标准模板库STL提供了模板类vetor,它是动态数组的替代品,C++11提供了模板类array,它是定长数组的替代品

指针总结:

1.声明指针

要声明指向特定类型的指针,请使用下面的格式:

typeName * pointerName;

// 下面是示例

double * pn;

char * pc;

// 其中,pn 和pc都是指针,而double * 和char *是指向double的指针和指向char的指针
2.给指针赋值

应将内存地址赋值给指针,可以对变量名应用&运算符,来获得被命名的内存的地址,new运算符返回未命名的内存的地址

下面是一些示例

double * pn;

double * pa;

double * pc;

double bubble = 3.2;

pn = &bubble;

pc = new char;

pa = new double[30];
  1. 对指针的解除引用

对指针解除引用意味着获得指针指向的值,对指针应用解除引用或间接值运算符()来解除引用,因此,如果像上面例子中那样,pn是指向bubble的指针,则pn是指向的值,即3.2

下面是示例:

cout << *pn
*pc = "s";

另一种对指针解除引用的方法是使用数组表示法,例如,pn[0]与*pn是一样的,绝不要对未被初始化为适当地址的指针解除引用

4.区分指针和指针所指向的值

如果pt是指向int的指针,则*pt不是指向int的指针,而是完全等同于一个int类型的变量,pt才是指针,

下面是示例:

int * pt = new int;
*pt = 5;
  1. 数组名

在多数情况下,C++将数组名视为数组的第一个元素的地址

下面是示例

int tacos[10];

一种例外情况是,将sizeof运算符用于数组名时,此时返回整个数组的长度(单位为字节)

  1. 指针算术

C++允许将指针和整数相加,加1的结果等于原来的地址值加上指向对象占用的总字节数,还可以将一个指针减去另一个值,获得两个指针的差,后一种运算将得到一个整数,仅当两个指针指向同一个数组(也可以指向超出结尾的一个位置)时,这种运算才有意义,这将得到两个元素的间隔

下面是一个示例

int tacos[10] = {5,2,8,4,1,2,2,4,6,8};
int * pt = tacos;      // suppose pf and tacos are the address 3000
pt = pt + 1;           // now pt is 3004 if a int is 4 bytes
int *pe = &tacos[9];   //pe is 3036 if an int is 4 bytes
pe = pe -1;            //now pe is 3032, the address of tacos[8]
int diff = pe - pt;    // diff is 7, the separation between
                       //tacos[8] and tacos[1]

猜你喜欢

转载自blog.csdn.net/u013693952/article/details/90726888