• 欢迎光临~

C++基础

开发技术 开发技术 2022-12-27 次浏览

输出语句

#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。
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"(stringn)",可以取消字符串内容里包含的转义字符

如果是R"aa(stringn)bb",效果同上

std::cout << R"(stringrtn)" << 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

*/

自动类型转换

  1. 当表达式中出现了不同类型混合运算,取值范围低的类型将会自动向范围高的进行转换
  2. 当表达式中含有浮点型时,将会自动向浮点类型转换
  3. 赋值时,左右操作数类型不一致,右操作数自动转换为左操作数类型,然后赋值
  4. 赋值时,右操作数超出了左操作数的取值范围,将会把右操作数截断后赋值给左操作数

强制类型转换

(类型)表达式

类型(表达式)

double d = 12.59;
int i = (int)d;
int k = int(d);
/*
i和k的值为12
*/

指针

常量指针

声明格式:const type* variable;

  1. 不能通过*variable修改(可以访问)variable指向的内存空间存放的内容,但是可以通过原变量名进行修改
  2. 可以更改variable的内容(可以更改指针的指向)
int a = 3, b = 5;
const int* p = &a;
*p=4; // 不能这样改
a = 4; // 这样可以
p = &b; // ok

常量指针一般用于修饰函数的形参,表示不希望在函数内部修改形参指向的内存空间的内容

指针常量(引用)

声明格式:type* const variable;

  1. variable的值不可以改变,因此声明的时候必须初始化
  2. 可以通过*variable修改variable指向的内存空间的内容

常指针常量(常引用)

声明格式:const type* const variable;

  1. variable的值不可改变,不能通过*variable改变variable指向的内存空间的内容,但是可以访问

CPP内存空间

程序运行时,内存主要分为四个区:栈、堆、数据段、代码段

  1. 栈:存放程序的局部变量、函数参数和返回值

  2. 堆:存放动态开辟内存的变量

  3. 数据段:存放程序中的全局变量和静态变量

  4. 代码段:存放可执行程序的二进制代码和常量

  5. 管理方式不同:栈是系统自动管理的,在出作用域时,将自动被释放;堆需手动释放,若程序中不释放,程序结束时由操作系统回收。

  6. 空间大小不同:堆内存的大小受限于物理内存空间;而栈就小得可怜,一般只有8M(可以修改系统参数)。

  7. 分配方式不同:堆是动态分配;栈有静态分配和动态分配(都是自动释放)。

  8. 分配效率不同:栈是系统提供的数据结构,计算机在底层提供了对栈的支持,进栈和出栈有专门的指令,效率比较高;堆是由C++函数库提供的。

  9. 是否产生碎片:对于栈来说,进栈和出栈都有着严格的顺序(先进后出),不会产生碎片;而堆频繁的分配和释放,会造成内存空间的不连续,容易产生碎片,太多的碎片会导致性能的下降。

  10. 增长方向不同:栈向下增长,以降序分配内存地址;堆向上增长,以升序分配内存地址。

动态分配内存

申请内存: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之后,应该赋值为空指针NULL0 ,C++11建议使用nullptr表示空指针,也就是(void*)0

Linux下如果使用nullptr,需要加-std=c++11参数

野指针

指向未分配的内存空间的指针

规避野指针:

  1. 定义指针时,初始化为nullptr
  2. 使用delete释放后,赋值为nullptr
  3. 函数不返回局部变量地址

函数指针

函数的地址就是函数在内存中的起始地址

使用函数指针

  1. 声明函数指针
  2. 让函数指针指向函数的地址
  3. 通过函数指针调用函数

函数指针的声明和调用

声明格式: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 );

  1. 数组起始地址

  2. 数组元素个数size_tunsigned long long

  3. 单个数组元素占用字节数

  4. 回调函数地址,回调函数应该符合int compare(const void* p1, const void* p2)

    1. 如果compare函数的返回值<0,那么p1所指向元素会被排在p2所指向元素的前面

    2. 如果函数返回值==0,那么p1和p2的排序顺序不确定

    3. 如果函数返回值>0,那么p1所指向的元素会被排在p2所指向的元素的后面

      int compare(const void* p1, const void* p2)
      {
          return *((int*)p1) - *((int*)p2); // 升序
          return *((int*)p2) - *((int*)p1); // 降序
      }
      
程序员灯塔
转载请注明原文链接:C++基础
喜欢 (0)