C++

第四章 复合类型

2019-01-28  本文已影响27人  鬼枭嗜

一、数组

C++数组从0开始编号。

数组不可以相互赋值。

在C++11中 初始化数组可以忽略等号,其次如果再大括号中不填入任何东西,这将吧所有元素设为0,同时列表初始化禁止缩窄转换。

二、字符串

字符串赋值...

拼接字符串常量

拼接字符串时前一个字符串的\0被下一个字符串第一个字符替代。

strlen()只计算可见的字符,而不把空字符计算在内。

cin使用空白(空格、制表符和换行符)来确定字符串的结束位置,这意味着cin在获取字符数组输入时之读取一个单词。读取该单词后,cin将该字符串放到数组中,并自动在结尾添加空字符。

每次读取一行字符串输入

面向行的输入:getline()

getline()函数读取整行,它通过回车键输入的换行符来确定输入结尾。要调用这种方法,可以使用cin.getline()。该函数有两个参数。第一个参数是用来储存输入行的数组的名称,第二个参数是读取字符数(包括了\0)。getline()成员函数在读取指定数目的字符或遇到换行符时停止读取并舍弃换行符。如果第一个字符是换行符,将会将一个空字符串赋给数组。

面向行的输入:get()

cin.get()用于读取下一个输入的字符。

cin.get(name,size)遇到换行符不再读取并将其留在输入序列中。

另一种方法是酱两个类成员函数拼接起来 cin.get(name,size).get()

之所以可以这样做,是由于cin.get(name,size)返回一个cin对象,该对象随后将被用来调用get()函数。

同样 cin.getline(name,size).getline(name,size);。也可。

当读取空行时 get()读取空行后将设置失效位置。这意味着加些来的输入将被阻断。可以用cin.clear()来恢复输入。

如果输入行包括的字符数比指定的多则getline()和get()将把余下的字符留在输入队列中,而getline()还会设置失效位,并关闭后面的输入。

混合输入字符串和数字

string类简介

头文件string #include<string>

string str1,str2;

可以使用c风格字符串来初始换string对象。可以使用cin来将键盘输入储存到string对象中。

可以使用cout来显示string对象。可以使用数组表书法方位储存在string对象中的字符。

str1=str2; //把2复制给1。 str1+=“xxx”//在str1后增添xxx。

string类具有自动调整大小的功能。

确定字符串字符数 int len1=str1.size(); //int len2=strlen(str2);

c函数使用参数来指出要使用哪个字符串,而C++ string类对象使用对象名和据点运算符来指出要使用哪个字符串。

使用getline读取string类 getline(cin,str);

C++结构 C++允许在声明结构变量时省略关键字struct

与数组一样,C++11也至此将列表初始化用于结构,且等号是可选的。

一定要让结构定义能够访问名称空间std。

结构体中的位字段

共用体

共用体是一种数据格式,它能够储存不同的数据类型,但只能同时储存其中一种类型,共用体长度为最大成员长度。

匿名共用体没有名称,其成员将成为位于相同地址处的变量,显然,每次只有一个成员是当前的成员。共用体常用于节省内存。

枚举...

指针和自由储存空间

指针定义方面略 详见后文。

指针的危险

在C++中创建指针时,计算机将分配用来储存地址的内存,但不会分配用来储存指针所指向的内存。

一定要在对指针应用解除引用运算符*之前,讲指针初始化为一个确定的适当的地址。

用new来分配内存。

在C语言,可以用库函数malloc()来分配内存;在C++中仍然可以这样做,但C++还有更好的方法———new运算符。

程序员要告诉new需要为哪种数据类型分配内存;new将找到一个长度正确的内存块,并返回该内存块的地址。程序员的责任是将该地址赋给一个指针。 例如 int * pn=new int;(相比malloc方便很多)

对于指针,需要指出的另一点是,new分配的内存块通常与常规变量声明分配的内存块不同。变量nights和pd的值都储存在中被称为栈的内存区域中,而new从被称为堆的自由储存区的内存区域分配内存。

内存被耗尽new将会返回空指针。

使用delete释放内存

例如delete p;(类比C语言中的free)

delete会释放指针所指向的内存,但不会删除指针本身,也就是说指针可以重新指向另一个内存块。

注意:只能用delete来释放使用new分配的内存。然而,对空指针使用delete是安全的。

使用new来创建动态数组。

int * psome= new int [10];

delete [] psome;

方括号告诉程序应该释放整个数组,而不仅仅是指针指向的元素。

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

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

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

        4.如果使用new为一个实体分配内存,则应使用delete来释放。

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

使用动态数组。可以直接使用psome[0]...psome=psome+1可以指向数组中下一个元素的地址。在使用delete释放动态数组时指针应该指向原来的值,这样可以给delete[]提供正确的地址。所以说 p[i]=*(p+i);注意的是数组名是不允许进行加一处理的。

指针、数组和指针算术。

同C一样C++将数组名解释为地址。指针加一会增加它所指向类型的字节数。

在多数情况下C++将数组名解释为数组第一个元素的地址。所以可以在指针初始化时让他等于数组名。

数组和指针第一个区别是可以修改指针的值,而数组名是常量。另一个区别是对数组应用sizeof运算符得到的是数组的长度,而对指针应用sizeof得到的是指针的长度。

对数组取地址(暂略 个人认为应该在二维数组等方面会详细涉及 详细将放在文尾)

使用数组声明来创建数组时,将采用静态联编,即数组的长度在编译时设置。

使用new[]运算符创建数组时,将采用动态联编(动态数组)(ps.这里是可以做变长数组的),即将在运行时位数组分配空间,其长度也将在运行时设置。使用完这种数组后,应使用delete[]释放其占用的内存。

数组和指针的特殊关系可以款占到C-风格字符串。

在C++中,用引号括起的字符串像数组名一样,也是第一个元素的地址。代码不会将整个字符串发送给cout,传递的是他们的地址。

在cout和多数C++表达式中,char数组名、char指针一级用引号括起的字符串常量都被解释为字符串的第一个字符的地址。

在将字符串读入程序是应使用已分配的内存地址。该地址可以使数组名,也可以是使用new初始化过的指针。

在用cout输出字符串时如果前面加上(int *)则会输出他的地址。

使用new创建动态结构

struct things{

int good;

int bad;

};

things grubnose={10,20};//grubnose是一个结构 他含有两个变量并进行了初始化。

things *p=&grubnose; pt指向结构grubnose。

引用方面 p->good等价于grubnose.good也等价于(*p).good。

自动储存、静态储存和动态储存。(C++新增了第四种类型———线程储存)

1.自动存储。

在函数内部定义的常规变量使用自动储存空间,被称为自动变量,这以为着他们在所属函数被调用时自动产生,在函数结束时消失。

实际上,自动变量是一个局部变量,其作用域为包含它的代码块。自动变量通常储存在栈中。这意味着执行代码块是,其中的变量将依次加入到栈中,而离开代码块时将按相反的顺序释放这些变量,这被称为先进后出。因此,在程序执行过程中,栈将不断地增大和缩小。

2.静态存储。

静态存储是整个程序执行期间都存在的储存方式。使变量成为静态的方式有两种:一种是在函数外面定义它;另一种是在声明变量时使用关键字static。

3.动态存储。

new和delete运算符提供了一种比自动变量和静态变量更灵活的方法。他们管理了一个内存池,这在C++中被称为自动存储空间或堆。该内存池同用于静态变量和自动变量的内存是分开的。new和delete可以在一个函数中分配内存,而在另一个函数中释放它。

内存泄漏...

类型组合...

数组的替代品

1.模板类vector

模板类vector类似于string类,也是一种动态数组。您可以在运行阶段设置vector对象的长度,可在末尾附加新数据,还可在中间插入新数据。基本上,他是使用new创建动态数组的替代品。实际上,vector确实使用new和delete来管理内存,但这种工作是自动完成的。

头文件要包含#include<vector>

vector<typename> vt(n_elem); //typename是类型 vt为数组名 n_elem为长度 可以不带(n_elem)默认为0。其中n_elem可以是整型常量也可以是整型变量。

2.模板类array

array长度固定,也使用栈。

array<typename,n_elem> arr。

不同的是 n_elem不能是变量。

在C++11中,可将列表初始化用于vector和array对象,但在C++98中,不能对vector对象这样做。

注意 double a1[3];

a1[-2]等价于*(a1-2)出现越界

vector和array同样。

一种解决方法是使用成员函数at()。 例如a2.at(1)=2.3。使用at()时将在运行期间捕获非法索引,而程序默认将中断。

(完)

很明显这章相比于前三章长了很多(正好3k字) 但是 相对来看 如果有一定编程基础的话本章其实应该较容易去理解 。


附上菜鸟教程。
http://www.runoob.com/cplusplus/cpp-variable-scope.html

http://www.runoob.com/cplusplus/cpp-pointers.html

http://www.runoob.com/cplusplus/cpp-arrays.html

http://www.runoob.com/cplusplus/cpp-array-of-pointers.html

http://www.runoob.com/cplusplus/cpp-pointers-vs-arrays.html

http://www.runoob.com/cplusplus/cpp-pointer-to-pointer.html

上一篇下一篇

猜你喜欢

热点阅读