输出语句
#include <iostream>
int main()
{
std::cout << "Hello World!\n"; // 输出HelloWorld
std::cout<<std::endl; // 输出换行
}
如果要使用cout输出变量的地址,最好是使用以下语句,否则cout可能将地址当做字符串处理
std::cout << (void*)&variable << std::endl;
命名空间
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!\n"; // 输出HelloWorld
cout<<endl; // 输出换行
}
变量
变量类型
int、float、double、char、string、bool(unsigned char)
signed:有符号的,可以表示正数和负数
unsigned:无符号的,只能表示正数
如果给bool变量赋值数字,非0将会被转换为1。
#include <iostream>
using namespace std;
int main()
{
cout << "Hello World!\n"; // 输出HelloWorld
cout << endl; // 输出换行
string name; // 姓名
int age;
double weight;
char sex;
bool flag;
name = "C Primer Plus";
age = 18;
weight = 500;
sex = 'M';
flag = true; // bool值在CPP里就是true:1 flase:0
cout << "name:" << name << " age:" << age << " weight:" << weight << " sex:" << sex << " flag:" << flag;
return 0;
}
变量作用域
全局变量和静态局部变量都会被自动初始化为0
输入语句
#include <iostream>
using namespace std;
int main()
{
cin >> name;
cout << name << endl;
}
C++11初始化赋值
int a = (15);
int b(20);
int a = {15};
int b{20};
在Linux平台,编译需要加-std=c++11参数
C++11的long long类型
在VS中,long是4字节,32位。 -2147483648~2147483647
在Linux中,long是8字节,64位。 -9223372036854775808~9223372036854775807
C++11标准增了long long类型的整数,至少64位,且至少与long一样长。
在VS中,long long是8字节,64位。 -9223372036854775808~9223372036854775807
在Linux中,long和long long类型都是8字节,64位。
ASCII
ASCII控制字符
十进制 | 符号 | 中文解释 | 十进制 | 符号 | 中文解释 |
---|---|---|---|---|---|
0 | NULL | 空字符 | 16 | DLE | 数据链路转义 |
1 | SOH | 标题开始 | 17 | DC1 | 设备控制 1 |
2 | STX | 正文开始 | 18 | DC2 | 设备控制 2 |
3 | ETX | 正文结束 | 19 | DC3 | 设备控制 3 |
4 | EOT | 传输结束 | 20 | DC4 | 设备控制 4 |
5 | ENQ | 询问 | 21 | NAK | 拒绝接收 |
6 | ACK | 收到通知 | 22 | SYN | 同步空闲 |
7 | BEL | 铃 | 23 | ETB | 传输块结束 |
8 | BS | 退格 | 24 | CAN | 取消 |
9 | HT | 水平制表符 | 25 | EM | 介质中断 |
10 | LF | 换行键 | 26 | SUB | 替换 |
11 | VT | 垂直制表符 | 27 | ESC | 换码符 |
12 | FF | 换页键 | 28 | FS | 文件分隔符 |
13 | CR | 回车键 | 29 | GS | 组分隔符 |
14 | SO | 移出 | 30 | RS | 记录分离符 |
15 | SI | 移入 | 31 | US | 单元分隔符 |
ASCII显示字符
十进制 | 符号 | 中文解释 | 十进制 | 符号 | 中文解释 |
---|---|---|---|---|---|
32 | 空格 | 80 | P | 大写字母 P | |
33 | ! | 感叹号 | 81 | Q | 大写字母 Q |
34 | " | 双引号 | 82 | R | 大写字母 R |
35 | # | 井号 | 83 | S | 大写字母 S |
36 | $ | 美元符 | 84 | T | 大写字母 T |
37 | % | 百分号 | 85 | U | 大写字母 U |
38 | & | 与 | 86 | V | 大写字母 V |
39 | ' | 单引号 | 87 | W | 大写字母 W |
40 | ( | 左括号 | 88 | X | 大写字母 X |
41 | ) | 右括号 | 89 | Y | 大写字母 Y |
42 | * | 星号 | 90 | Z | 大写字母 Z |
43 | + | 加号 | 91 | [ | 左中括号 |
44 | , | 逗号 | 92 | \ | 斜线 |
45 | - | 减号 | 93 | ] | 右中括号 |
46 | . | 句点或小数点 | 94 | ^ | 音调符号 |
47 | / | 反斜线 | 95 | _ | 下划线 |
48 | 0 | 数字0的符号 | 96 | ` | 重音符 |
49 | 1 | 数字1的符号 | 97 | a | 小写字母 a |
50 | 2 | 数字2的符号 | 98 | b | 小写字母 b |
51 | 3 | 数字3的符号 | 99 | c | 小写字母 c |
52 | 4 | 数字4的符号 | 100 | d | 小写字母 d |
53 | 5 | 数字5的符号 | 101 | e | 小写字母 e |
54 | 6 | 数字6的符号 | 102 | f | 小写字母 f |
55 | 7 | 数字7的符号 | 103 | g | 小写字母 g |
56 | 8 | 数字8的符号 | 104 | h | 小写字母 h |
57 | 9 | 数字9的符号 | 105 | i | 小写字母 i |
58 | : | 冒号 | 106 | j | 小写字母 j |
59 | ; | 分号 | 107 | k | 小写字母 k |
60 | < | 小于 | 108 | l | 小写字母 l |
61 | = | 等号 | 109 | m | 小写字母 m |
62 | > | 大于 | 110 | n | 小写字母 n |
63 | ? | 问号 | 111 | o | 小写字母 o |
64 | @ | 电子邮件符号 | 112 | p | 小写字母 p |
65 | A | 大写字母 A | 113 | q | 小写字母 q |
66 | B | 大写字母 B | 114 | r | 小写字母 r |
67 | C | 大写字母 C | 115 | s | 小写字母 s |
68 | D | 大写字母 D | 116 | t | 小写字母 t |
69 | E | 大写字母 E | 117 | u | 小写字母 u |
70 | F | 大写字母 F | 118 | v | 小写字母 v |
71 | G | 大写字母 G | 119 | w | 小写字母 w |
72 | H | 大写字母 H | 120 | x | 小写字母 x |
73 | I | 大写字母 I | 121 | y | 小写字母 y |
74 | J | 大写字母 J | 122 | z | 小写字母 z |
75 | K | 大写字母 K | 123 | { | 左大括号 |
76 | L | 大写字母 L | 124 | | | 竖线 |
77 | M | 大写字母 M | 125 | } | 右大括号 |
78 | N | 大写字母 N | 126 | ~ | 波浪号 |
79 | O | 大写字母 O | 127 | 删除 |
转义字符
ASCII码值 | 转义字符 | 含义 |
---|---|---|
0 | \0 | 空,给字符型变量赋值时可以直接书写0。 |
10 | \n | 换行(LF) ,将当前位置移到下一行开头。 |
13 | \r | 回车(CR) ,将当前位置移到本行开头 |
9 | \t | 水平制表(HT) (跳到下一个TAB位置) |
92 | \ | 斜线 |
34 | " | 双引号,书写字符时不必转义。 |
39 | ' | 单引号,书写字符串中不必转义。 |
7 | \a | 警报 |
8 | \b | 退格(BS) ,将当前位置移到前一列 |
12 | \f | 换页(FF),将当前位置移到下页开头 |
11 | \v | 垂直制表(VT) |
C++11的原始字面量
格式:R"(字符串内容)"
使用R"(string\n)"
,可以取消字符串内容里包含的转义字符
如果是R"aa(string\n)bb"
,效果同上
std::cout << R"(string\r\t\n)" << std::endl;
字符串型
C++字符串:string 变量名 = "字符串内容" ;
C字符串:char 变量名[] = "字符串内容" ;
C风格字符串的本质是字符数组,C++风格字符串的本质是类,它封装了C风格字符串。
赋值:变量名 = "字符串内容" ;
拼接:变量名 = 变量名+ "字符串1" + "字符串2" + "字符串的内容n";
字符串比较:支持关系运算符
#include <iostream>
int main()
{
string str = "123";
if(str == "123")
std::cout << "true" << std::endl;
}
如果字符串内容都是常量,则不能使用加号(+)拼接
string str;
str = "123" + "string" + "abc"; // 不能这样使用
如果内容过长,可以多行书写
string str;
str = "123"
"string""abc";
/*
输出结果为
123stringabc
*/
自动类型转换
- 当表达式中出现了不同类型混合运算,取值范围低的类型将会自动向范围高的进行转换
- 当表达式中含有浮点型时,将会自动向浮点类型转换
- 赋值时,左右操作数类型不一致,右操作数自动转换为左操作数类型,然后赋值
- 赋值时,右操作数超出了左操作数的取值范围,将会把右操作数截断后赋值给左操作数
强制类型转换
(类型)表达式
类型(表达式)
double d = 12.59;
int i = (int)d;
int k = int(d);
/*
i和k的值为12
*/
指针
常量指针
声明格式:const type* variable;
- 不能通过
*variable
修改(可以访问)variable指向的内存空间存放的内容,但是可以通过原变量名进行修改 - 可以更改variable的内容(可以更改指针的指向)
int a = 3, b = 5;
const int* p = &a;
*p=4; // 不能这样改
a = 4; // 这样可以
p = &b; // ok
常量指针一般用于修饰函数的形参,表示不希望在函数内部修改形参指向的内存空间的内容
指针常量(引用)
声明格式:type* const variable;
- variable的值不可以改变,因此声明的时候必须初始化
- 可以通过
*variable
修改variable指向的内存空间的内容
常指针常量(常引用)
声明格式:const type* const variable;
- variable的值不可改变,不能通过*variable改变variable指向的内存空间的内容,但是可以访问
CPP内存空间
程序运行时,内存主要分为四个区:栈、堆、数据段、代码段
-
栈:存放程序的局部变量、函数参数和返回值
-
堆:存放动态开辟内存的变量
-
数据段:存放程序中的全局变量和静态变量
-
代码段:存放可执行程序的二进制代码和常量
-
管理方式不同:栈是系统自动管理的,在出作用域时,将自动被释放;堆需手动释放,若程序中不释放,程序结束时由操作系统回收。
-
空间大小不同:堆内存的大小受限于物理内存空间;而栈就小得可怜,一般只有8M(可以修改系统参数)。
-
分配方式不同:堆是动态分配;栈有静态分配和动态分配(都是自动释放)。
-
分配效率不同:栈是系统提供的数据结构,计算机在底层提供了对栈的支持,进栈和出栈有专门的指令,效率比较高;堆是由C++函数库提供的。
-
是否产生碎片:对于栈来说,进栈和出栈都有着严格的顺序(先进后出),不会产生碎片;而堆频繁的分配和释放,会造成内存空间的不连续,容易产生碎片,太多的碎片会导致性能的下降。
-
增长方向不同:栈向下增长,以降序分配内存地址;堆向上增长,以升序分配内存地址。
动态分配内存
申请内存:new type(initval); // C++11支持{}
new type[size];
释放内存:delete address;
int* p = new int(5);
std::out << *p << std::endl; // 输出5
delete p;
p = NULL;
int* arr = new int[10]; // 申请10个int类型的内存空间
delete arr;
arr = NULL;
对空指针进行delete不会出错,系统会忽略该操作,内存释放后,应该将指针指向NULL
空指针
指针被delete之后,应该赋值为空指针NULL
或0
,C++11建议使用nullptr表示空指针,也就是(void*)0
Linux下如果使用nullptr,需要加-std=c++11
参数
野指针
指向未分配的内存空间的指针
规避野指针:
- 定义指针时,初始化为nullptr
- 使用delete释放后,赋值为nullptr
- 函数不返回局部变量地址
函数指针
函数的地址就是函数在内存中的起始地址
使用函数指针
- 声明函数指针
- 让函数指针指向函数的地址
- 通过函数指针调用函数
函数指针的声明和调用
声明格式:retval_type(*funptr)(type1, type2, typen);
C++调用:funptr(type1_val, type2_val, typen_val);
C调用:(*funptr)(type1_val, type2_val, typen_val);
一维数组
数组的声明
语法:type array[length];
length必须是整数,可以是常量,也可以是变量和表达式
C90规定必须用常量表达式指定数组大小,C99允许使用整型非常量表达式,Linux中可以使用变量
数组占用内存
使用sizeof(array)
函数可以得到数组占用空间大小(字节),但是只适用于C++的基本数据类型
数组的初始化
type array[length] = { val1, val2, val3, valn };
type array[] = { val1, val2, val3, valn };
type array[length] = { 0 };
type array[length] = {};
C++11可以不写等号
清空数组
void *memset(void *_Dst, int _Val, size_t _Size);
Linux下使用需要包含string.h头文件
复制数组
void *memcpy(void *_Dst, const void *_Src, size_t _Size);
Linux下使用需要包含string.h头文件
数组名是地址
数组名不一定会被解释为地址,使用sizeof(array)
时,返回array数组占用的内存字节数
数组名是常量,不可更改
数组名作为函数的参数
使用数组名/数组首地址作为函数的形参,函数有两种定义方式
retval_type fun(type* array_ptr);
retval_type fun(type array_ptr[]);
在函数内部,不要对指针array_ptr使用sizeof函数,它不是数组名
使用new动态创建一维数组
语法:type* array_ptr = new type[length];
释放:delete[]array_ptr
声明普通数组的时候,数组长度可以用变量,相当于在栈中动态创建数组,并且不需要释放
如果内存不足,调用new会产生异常,导致程序中止,如果在new后面加(std::nothrow)
则返回nullptr,不会产生异常,之后可以对指针判空,避免异常导致的崩溃
使用delete[]释放,不需要指定数组大小,系统会自动跟踪已经分配数组的内存
数组的排序
void qsort(void *_Base, size_t NumOfElements, size_t _SizeOfElement, _CoreCrtNonSecureSearchSortCompareFunction _CompareFunction );
-
数组起始地址
-
数组元素个数
size_t
是unsigned long long
-
单个数组元素占用字节数
-
回调函数地址,回调函数应该符合
int compare(const void* p1, const void* p2)
-
如果compare函数的返回值<0,那么p1所指向元素会被排在p2所指向元素的前面
-
如果函数返回值==0,那么p1和p2的排序顺序不确定
-
如果函数返回值>0,那么p1所指向的元素会被排在p2所指向的元素的后面
int compare(const void* p1, const void* p2) { return *((int*)p1) - *((int*)p2); // 升序 return *((int*)p2) - *((int*)p1); // 降序 }
-