C++ Prime Plus 知识点整理 - 第四章 复合类型

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/hzt12345hf/article/details/84763096

C++三种复合类型:数组、结构和指针

数组

  • 数组声明**typeName arrayName[arraySize];**,其中arraySize必须为常量值
  • 数组初始化,C语言为typeName arrayName[arraySize] = {value1, value2, value3, ...};,C++新增方法typeName arrayName[arraySize]{value1, value2, value3, ...};,如果括号里为空,则个元素都设置为零,但初始化列表禁止缩窄转换,如:long p[ ] {23, 93, 3.0} 是不允许的;

字符串

  • 字符串都以字符'\0'结尾,用双引号括起来的字符串称为字符串常量或字符串字面值;区别字符数组和字符串,字符串内置结束字符,而字符数组没有;

###字符和字符串的输入输出

  • 默认cin遇到空格、制表符、换行符时自动结束字符串输入,意味着不可以输入带有空格的字符串,如果要输入一样字符串,则使用istream中面向行的类成员函数 getline()get()
  • cin.getline(char *arrayName , int size);,arrayName表示数组名,size表示最多读入多少个字符,getline()函数遇到换行符结束输入,读取换行符,不将其留在输入队列中
  • cin.get(char *arrayName , int size);,arrayName表示数组名,size表示最多读入多少个字符,get()函数遇到换行符结束输入但不读取换行符,而是将其留在输入队列中,因此需要再调用一次cin.get()来读取下一个字符;可以将两个get()结合起来cin.get(char *arrayName , int size).get();;当get()读取到空行后将设置失效位(failbit),会阻塞输入,要使用 cin.clear(); 来恢复输入;
  • 一般的 cin>>x 输入会将换行符留在输入队列,因此如果要用getline()和get(),需要将剩余的换行符清除,可以这么写(cin>>x).get();
  • cin、getline、get对比:
对比 cin>>xxx cin.getline(xxx,size) cin.get(xxx,size)
作用 输入基本类型数据 输入整行字符串 输入整行字符串
结束标志 空格、制表符、换行符 换行符 换行符
换行符去留 留在输入队列中 换行符已使用 留在输入队列中
  • 读取字符可以使用cin.get(ch);ch = cin.get();,使用cout.put(ch);输出字符;cin.get(ch)和ch = cin.get()区别如下:
属性 cin.get(ch) ch = cin.get()
传递输入字符的方式 赋值给参数ch 将函数返回值赋给ch
用于字符输入是函数的返回值 istream对象(执行bool转换后为true) int类型的字符编码
到达EOF是函数的返回值 istream对象(执行bool转换后为false) EOF

字符函数库cctype

  • C++从C那里继承了一个与字符相关的便捷的函数库,C中头文件为ctype.h,C++为cctype;
    在这里插入图片描述

string类

  • 要使用string类,需要包含头文件string,string对象和字符数组方式基本相同,C语言提供了头文件cstring(以前是string.h)来处理字符串;
  • string类字符串可以用cin输入,cout输出,不过string自己实现了getline()类方法 getline(istream &in, string &str);,其中in表示标准输入类的实例,一般使用cin,str表示要输入到的string类对象
  • C++11 新增了原始字符串,即字符串中不存在转义字符,每个字符都代表自己,原始字符串使用 "()" 作为定界符, 前缀R 标识原始字符串,允许在“和(直接添加东西来替换原始的定界符,但定界符前后要对称,举例如下: cout << R"+\*("(Who wouldn't?)" , she whispered.)+\*" << endl; 其中定界符为 “+*( 和 )*+”

结构体、共用体和枚举体

  • struct: C++允许声明结构变量时省略关键字struct,也允许使用不带等号的初始化方式,但不允许缩窄转换,可以像C语言一样设置位字段来方便与寄存器对应
  • union:共用体可以节省空间,匿名共用体没有名称,其成员位于同一地址处,显然每次只有一个成员是当前的成员,举例如下
struct widget
{
	char brand[30];
	int type;
	union
	{
		long id_num;
		char id_char[20];
	}; //分号要注意
};
...
widget prize;
...
if(prize.type == 1)
	cin >> prize.id_num;
else
	cin >> prize.id_char;
  • enum:枚举体可以代替const方式定义的常量;枚举的值进行计算时会提前转换为整型,因为枚举类型并没有定义运算,但是要注意C++11的类内枚举的区别;枚举体取值范围定义如下:首先,找出上限,找到比枚举体最大值大的第一个2的幂,减去1即为取值范围的上限,计算下限,如果不小于0,则0就是下限,否则采用寻找上限一样的方法寻找下限;采用多少空间来存储由编译器决定

new、指针、数组

  • 常规变量存储在栈(stack)的内存区域,而new从堆(heap)或自由存储区(free store)的内存区域分配内存;
  • 面向对象编程更多的强调运行阶段(而不是编辑阶段)进行决策,指针可以使用new运算符,可在运行阶段分配内存,C++提供了检测并处理内存分配失败的工具;delete用来释放内存,如果不释放内存则有可能导致内存泄漏,而释放已经释放的内存块将导致不确定的结果;
int * d = new int;
//...
delete d;
  • 编译时分配给数组的内存称为静态联编(static binding),运行阶段分配的内存称为动态联编(dynamic binding),此数组也成为动态数组**type_name * pointer_name = new type_name[num_elements];**;数组名和指针基本等价是C和C++的一个优点
int * d = new int[10];
//...
delete []d;
  • 指针变量+1后,其增加的值等于指向的类型占用的字节数;
  • 指针和数组操作方式很多情况下相同,可以使用数组方括号表示法也可以使用解除引用运算符法;指针的值可以修改,但数组名是常量,而且sizeof()对数组名使用将会得到数组的长度,对指针使用只得到指针的长度;数组名表示数组第一个元素的地址,对数组名应用地址运算符时,得到的是整个数组的地址;
int a;
int * b;
int c[20];
b = &a;	
b = c; 
cout << c[0] << *(c+1) << b[0] << *(b + 1) << endl;//指针和数组操作类似,数组表示法、指针表示法
  • new可以用来创建动态结构;如果结构标示是结构名,则使用局点运算符(.);如果标识符是指向结构的指针,则使用箭头运算符(->),还可以这样(*p).name; ,但一定要加括号

分配内存方式

  • C++有4种分配内存方式:自动存储静态存储动态存储线程存储(C++11新增)

自动存储:函数内部定义的常规变量使用自动存储空间,被称为自动变量,这意味着函数被调用时自动产生,函数调用结束时消亡;
静态存储:整个程序执行期间一直存在的存储方式,定义静态变量可以定义在函数外面,也可以使用关键字static声明;
自动存储和静态存储的关键在于严格限制了变量的寿命
动态存储:使用new定义的变量,数据的生命周期不完全受程序或函数的生存时间控制,这也导致内存管理变得更复杂

vector和array模板类

  • vector模板类,需要包含头文件vector,定义方式:vector<typeName> vt(n_elem); ,n_elem可选填,可以整型常量也可以是整型变量;
  • array模板类,C++11新增,需要包含头文件array,定义方式:array<typeName, n_elem> arr;,n_elem必填,且不能是变量;array模板类长度固定,使用栈空间;
  • vector和array都不检测数组越界,然而两者共有的at()成员函数可以在运行期间捕获非法索引,如:a.at(1) = 3;

猜你喜欢

转载自blog.csdn.net/hzt12345hf/article/details/84763096