数组
-
char ch[] ch必须定义时负值、不能做左值
-
C++11 char ch[] {} ; char ch[] = {};
-
strcpy(charr1,charr2); strcat(charr1,charr2); (头文件cstring string.h) 拓展:strncat strncpy 可以指出长度
-
cin.getline(charr1,num);是类方法
-
确定长度 strlen(ch1)
string
-
C++11初始化 string ch[] {} ; string ch[] = {};
-
str += str; str = str1 + str2;
-
getline(cin,str);不是类方法 istream类中只有处理double、int等的方法,没有处理string的方法 cin >> str 是利用友元函数处理的
-
确定长度 strlen(ch1) str.size()
其他形式的字符串字面值
wchar_t title[] = L"chief Astrogator";
char16_t name[] = u"Felonia Ripova";
char32_t car[] = U"Humber Super Snipe";
C++11 还支持Unicode字符编码方案UTF-8 根据编码的数字值,字符可能存储1-4个八位组,用前缀u8表示。
raw (C++11新增)原始字符串 :表示的字符串就是自己
cout << R"(Jim "King" Tutt uses "\n" instead of endl.)" << '\n';
其中输入原始字符串时,按回车不仅会移到下一行,该将在原始字符串中添加回车字符。
输出Jim "King" Tutt uses "\n" instead of endl.
为了使得能输出)
R"...(...(...)...)..." 输出...(...)... ...自定义定界符不能用空格、左右括号、斜杆和控制字符(如制表符和换行符)
get() getline():读取一整行
cin.getline(char *,int a) 最多读取a-1字符 读取并丢弃换行符
cin.get(char *,int a)最多读取a-1字符 读取换行符并将它留在输入队列 (调用get()来处理,例如cin.get(name,20).get()) get可以用来检错。
混合输入字符串和数字的问题:cin读取年份,将回车键生成的换行符留在队列中导致cin.getline()以为是空行。
int year;
cout << "shuru year:";
cin >> year;
cout << "shuru address";
char address[80];
cin.getline(address,80);
struct
-
声明与创建
struct name { ... }; struct name { ... }n1,n2; struct name { ... }n1= { , , }; struct { ... }n1;
-
相对于c,可以省略struct struct xxx a; xxx a;
-
初始化 xxx a = {,,};xxx a {,,};xxx a {}(成员都为0,不允许缩窄转换)
-
name n1 ,n2. 允许n2=n1;
-
结构数组
inflatable gifts[2] = { {,,}, {,,} };
-
结构中的位字段 :num 指定了位数 例如:unsigned int SN :4; 还可以使用没有名称的字段提供间距,例如:unsigned int :4;
union
-
共用体能够存储不同的数据类型,但只能同时存储其中的一种类型
-
共用体的长度为其最大成员的长度。
-
共用体一般用来解决某个数据项有两种或多种格式。例如一些商品的ID为整数,一些为字符串。
-
共用体可以用来节省内存,一般会用于嵌入式编程。
struct widget { char brand[20]; int type; union id { long id_num; char id_char[20]; }id_val; }; int main() { widget prize; prize.type = 1; if (prize.type == 1) cin >> prize.id_val.id_num; else cin >> prize.id_val.id_char; return 0; } struct widget { char brand[20]; int type; union { long id_num; char id_char[20]; }; }; int main() { widget prize; prize.type = 1; if (prize.type == 1) cin >> prize.id_num; else cin >> prize.id_char; return 0; }
enum
-
提供创建符号常量的方式,定义新类型。
enum spectrum {red,orange,yellow,green,blue,violet,indigo,ultraviolet } //范围是0~7,如果只使用常量,而不创建枚举类型可省略 spectrum spectrum band;
-
只有赋值运算,没有算术运算。band = blue //valid band ++ ; band = red + orange; //invalid
-
枚举量是整型,可以提升到int,但int不能自动转换到枚举类型。 可以通过强制转换,例如:
int a = 3+red //invaid band = spectrum(3); //invaid
-
可以使用赋值运算符来显示地设置枚举量的值,第一位默认为0,后面未初始化的值比前面的大1
enum bits{first,second = 100, third}
也可以创建多个相同的枚举值
enum {zero, null = 0,one,numero_uno = 1};
-
枚举的取值范围
最小值不小于0时 0~大于最大值的最小的2的幂-1
最小值小于0是 -(大于最小值的最小的2的幂-1)~大于最大值的最小的2的幂-1
因此即便不是枚举值,位于枚举范围内也合法,例如:
bits myflag= bits(6);
指针
-
C++创建指针时,会分配用来存储地址的内存,而不会分配用来存储指针指向的数据的内存。因此一定要在对指针应用解除应用运算符(*)之前,将指针初始化为一个确定的、适当的地址。
int* p; *p = 23333; //invalid int a; *p = &a; *p = 23333;
-
指针和整型是不同的类型
int *pt pt = 0xB8000000 //invalid type mismatch pt = (int*)0xB8000000 //valid
自由存储空间 new delete
-
new将找到一个长度正确的内存块,返回内存块的地址。typeName* pointer_name = new typeName;
-
new分配的内存块通常与常规变量声明分配的内存块不同。变量和指针变量都是存储在称为栈(stack)的内存区域,而new从称为堆(heap)或自由存储区(free store)的内存区域。
-
内存耗尽 new返回空指针
-
delete会释放指针指向的内存,而不会删除指针本身。可以使用重新指向一个新分配的内存块。
-
new和delete一定要配对使用,否则会发生内存泄漏。
int* ps = new int; delete ps; //valid delete ps; //not OK now int jugs = 5; ps = &jugs; delete ps; //invalid ,memory not allocated by new int* ps = new int; int *pq =ps; delete pq; //valid
-
动态联编:在运行阶段创建
静态联编:在编译阶段分配内存
-
动态数组
int * psome = new int [10]; delete [] psome;
-
规则:
不要使用delete来释放不是new分配的内存
不要使用delete释放同一个内存两次
对空指针应用delete是安全的
使用new [] 应使用delete []
使用new ,应使用 delete;
-
new返回的指针指向数组的第一个元素,不能使用sizeof运算符来确定动态分配的数组的字节数。当系统是知道分配的内存量的,以便delete[]
-
指针可当做数组名来使用,运行指针加1,但不允许数组名加1(因为数组名是常量)。例如 :
int * psome = new int [10]; psome[0] = 1; psome += 1; psome -= 1; delete [] psome; //要使指针指向原处 int arr[10]; arr +=1;//invalid
指针、数组和指针算术
-
数组名是第一个元素地址,是常量
int arr[10]; int* p,q; p = arr; q = &arr[0];
-
arrayname[i] -> *(arrayname + 1) pointername[i] -> *(pointername + 1)
-
指针可加1,每加1,移动类型字节数,但不允许数组名加1
-
sizeof pointername 得到指针类型长度 sizeof arrayname 得到数组长度(这是c++不会把数组名解释为地址)
-
&arrayname 是数组大小内存块的地址 P109
&arrayname + 1 代表移动数组大小的字节
short (*pointername)[20] = &arrayname; pointername 类型为 short (星号)[20]
因此 *pointername 与 arrayname等价
指针与字符串
-
char数组名、char指针和“ ”内的字符串常量都被解释为字符串第一个字符的地址
-
一般来说,如果给cout提供一个指针,它将打印地址,但如果是char * 指针,将显示指向的字符串,可能通过(int *)来显示字符串的地址
-
strncpy
char food[20]; strncpy(food,"as sdalkw sdkla; sdakl2na",19); food[19] = '\0';
指针与结构体
-
如果标识符为结构体名,使用句号运算符(.);如果标识符是指针,使用->;
struct inflatable { char name[20]; float volume; double price; }; int main { inflatable *ps = new inflatable; cin.get(ps->name, 20).get(); cout << "next"; inflatable inf1; cin.get(inf1.name, 20); return 0; }
-
指针指向结构体要用取地址符&。
内存存储--自动存储、静态存储、动态存储、线程存储(C++11)
-
自动存储,一般存储在栈中,后进先出。一般为局部变量,函数调用使自动产生,函数结束时消灭。
-
静态存储(两种) 全局变量和变量前使用关键字static。存活于整个生命周期,也可能只在特定函数被执行存在。
-
new delete;它们管理一个内存池(被称为自由存储空间和堆)。不完全没受程序或函数的生存空间控制。
类型组合
#include
#include
using namespace std;
struct years_end
{
int year;
};
int main()
{
years_end s1, s2, s3;
s1.year = 2018;
years_end *p = &s2;
p->year = 2019;
years_end arr[3];
arr[0].year = 2020;
(arr + 1)->year = 2021;
const years_end *ps[3]{&s1,&s2,&s3};
//ps[2]->year = 2022;
cout << ps[0]->year << (*(ps+1))->year;
auto ass = ps;
cout << (*ass)->year <<(*(ass+1))->year;
const years_end **pa = ps;
cout << (*pa)->year << (*(pa + 1))->year;
return 0;
}
vector array
-
(C++98)vector vt(n_elem); n_elem可以是整型常量,也可以是整型变量。 长度不固定,动态的。
-
(C++11)array arr; n_elem不能是变量。长度固定,静态的。