C++ 一些要点

要点

ASCII 码

ASCII值控制字符ASCII值控制字符ASCII值控制字符ASCII值控制字符
0NUT32(space)64@96
1SOH33!65A97a
2STX34"66B98b
3ETX35#67C99c
4EOT36$68D100d
5ENQ37%69 zE101e
6ACK38&70F102f
7BEL39'71G103g
8BS40(72H104h
9HT41)73I105i
10LF42*74J106j
11VT43+75K107k
12FF44,76L108l
13CR45-77M109m
14SO46.78N110n
15SI47/79O111o
16DLE48080P112p
17DCI49181Q113q
18DC250282R114r
19DC351383S115s
20DC452484T116t
21NAK53585U117u
22SYN54686V118v
23TB55787W119w
24CAN56888X120x
25EM57989Y121y
26SUB58:90Z122z
27ESC59;91[123{
28FS60<92/124|
29GS61=93]125}
30RS62>94^126`
31US63?95_127DEL

操作系统标准I/O重新定向

将标准I/O重新定向到其他设备

< 重新定向标准输入

>>> 重新定向标准输出

| 管道操作(将左侧命令的输出作为右侧的输入)

多种不同方式的运行

使用操作系统(如:Windows)的 I/O 重新定向功能运行 可执行文件 Hello.exe

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Hello 

Hello < Input.txt 

Hello > Output.txt 

Hello >> Output.txt 

Hello < Input.txt > Output.txt 
Hello < Input.txt >> Output.txt 

type Input.txt | Hello 
type Input.txt | Hello > Output.txt 

可将这些命令写入“批处理文件”(即命令处理程序)中

批处理文件(*.bat文件)

批处理(batch,以bat为扩展名),也称为脚本,其本质是一批操作系统命令按一定顺序排列而形成程序。

批处理中支持条件分支、循环等结构。

批处理文件格式为文本文件(可用 Windows 的记事本等文本编辑软件进行编辑),基本上每一行为一条命令。

C/C++等语言所生成的可执行文件(.exe)是一种操作系统命令。

常用的命令有

echo 输出字符串

rem 注释

pause 暂停,按任意键继续

引用

概念

引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样

1
2
int a;
int &ra = a;

说明

  1. &在此不是求地址运算,而是起标识作用

  2. 引用声明完毕后,相当于目标变量名有两个名称,即该目标原名称和引用名,且不能再把该引用名作为其他变量名的别名。

  3. ra=1; 等价于 a=1;

  4. 声明一个引用,不是新定义了一个变量,它只表示该引用名是目标变量名的一个别名,它本身不是一种数据类型,因此引用本身不占存储单元,系统也不给引用分配存储单元。故:对引用求地址,就是对目标变量求地址。&ra&a相等

  5. 不能建立数组和函数的引用

  6. 优点:使用引用传递函数的参数,在内存中并没有产生实参的副本,它是直接对实参操作;而使用一般变量传递函数的参数,当发生函数调用时,需要给 形参分配存储单元,形参变量是实参变量的副本;如果传递的是对象,还将调用拷贝构造函数。因此,当参数传递的数据较大时,用引用比用一般变量传递参数的效 率和所占空间都好

  7. 与指针比较:使用指针作为函数的参数虽然也能达到与使用引用的效果,但是,在被调函数中同样要给形参分配存储单元,且需要重复使用"*指针变量名“的形式进行运算,这很容易产生错误且程序的阅读性较差;另一方面,在主调函数的调用点处,必须用变量的地址作为实参。而引用更容易使用,更清晰。

常引用

1
2
int a;
const int &ra = a;

用这种方式声明的引用,不能通过引用对目标变量的值进行修改,从而使引用的目标成为const,达到了引用的安全性。

值传递、指针传递、引用传递

值传递

形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参),参数的值只能传入,不能传出。当函数内部需要修改参数,并且不希望这个改变影响调用者时,采用值传递。

指针传递

形参为指向实参地址的指针,当对形参的指向操作时,就相当于对实参本身进行的操作

引用传递

形参相当于是实参的“别名”,对形参的操作其实就是对实参的操作,在引用传递过程中,被调函数的形式参数虽然也作为局部变量在栈

中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过

栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量

整型例

  1. 值传递

    1
    2
    3
    
    void change1(int n);
    
    change1(n);
    
  2. 指针传递

    1
    2
    3
    
    void change2(int *n);     //函数内需要间址取值
    
    change2(&n);
    
  3. 引用传递

    1
    2
    3
    
    void change3(int &n);
    
    change3(n);
    

重载函数

  • 定义

    函数名相同,不同的参数搭配时,含义不同

  • 允许重载的条件

    • 参数类型不同
    • 参数个数不同
    • 参数顺序不同

    满足一条即可重载

  •  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    
    int func(int x)
    {
    	return x;
    }
    int func(int x,int y)
    {
        return x + y;
    }
    int func(const char *s)
    {
    	return strlen(s);
    }
    

函数模板

  • 概念

    建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表

  • 语法

    template <typename T>

    • template — 声明创建模板

    • typename — 表面其后面的符号是一种数据类型,可以用class代替

    • T — 通用的数据类型,名称可以替换,通常为大写字母

    调用

    func(a,b);func<int>(a,b);

  • 使用多个虚类型

    1
    2
    3
    4
    
    template <class T1, class T2>
    void func(T1 a, T2 b) { .... }
    //调用
    func<int,double>(a,b);
    

内联函数

  • 概念

    • 定义:当函数被声明为内联函数之后, 编译器会将其内联展开, 而不是按通常的函数调用机制进行调用.
    • 优点: 当函数体比较小的时候, 内联该函数可以令目标代码更加高效. 对于存取函数以及其它函数体比较短, 性能关键的函数, 鼓励使用内联.
    • 缺点: 滥用内联将导致程序变慢. 内联可能使目标代码量或增或减, 这取决于内联函数的大小. 内联非常短小的存取函数通常会减少代码大小, 但内联一个相当大的函数将戏剧性的增加代码大小. 现代处理器由于更好的利用了指令缓存, 小巧的代码往往执行更快。
  • 基本使用

    在函数前加inline即可

带有默认值参数的函数

  • 定义

    C++允许实参个数与形参个数不同。在声明函数原型时,为一个或多个形参指定默认值,以后调用此函数时,若省略其中某一实参,C++自动的以默认值作为相应参数的值。

  • 例子

    1
    2
    3
    4
    5
    6
    
    //声明
    int special(float x = 5, float y = 5.3);
    //调用
    special(100, 79.8); //x = 100, y = 79.8
    special(25);        //x = 25, y = 5.3
    special();          //x = 5, y = 5.3
    

new与delete

new

  • 格式

    new 类型(初值)

    new 类型[大小]

  •  1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    
    new int;
    //开辟一个存放整数的存储空间,返回地址(即指针)
    
    new int(100);
    //开辟一个存放整数的空间,并指定该整数的初值为100,返回地址
    
    new char[10];
    //开辟一个存放字符数组(包括10个元素)的空间,返回首元素的地址
    
    new int[5][4];
    //开辟一个存放二维整型数组(大小为5*4)的空间,返回首元素的地址
    
    float *p=new float (3.14159);
    //开辟一个存放单精度数的空间,并指定该实数的初值为//3.14159,将返回的该空间的地址赋给指针变量p
    
  • 要点

    用 new 分配数组空间时不能指定初值。

    如果由于内存不足等原因而无法正常分配空间,则 new 会返回一个空指针 NULL,用户可以根据该指针的值判断分配空间是否成功

delete

  • 格式

    delete [ ] 指针变量

    delete 变量

函数返回字符串

  • 使用 static

    1
    2
    3
    4
    5
    
    char *func()
    {
    	static char str[5];
    	return str;
    }
    
  • 使用全局变量

    1
    2
    3
    4
    5
    6
    
    char str[5];
    char *func()
    {
    	//...
    	return str;
    }
    

异常处理

概念

  1. 异常是程序执行期产生问题,比如尝试除以零的操作。

  2. 异常提供了一种转移程序控制权的方式。C++ 异常处理涉及到三个关键字:trycatchthrow:

  3. 关键字

    throw: 当问题出现,程序通过 throw 抛出一个异常;

    catch: 在你想要处理问题的地方,通过异常处理程序捕获异常;

    try: try 块中的代码标识将被激活的特定异常。它后面允许跟着一个或多个 catch 块;

抛出异常

使用 throw 语句在代码块中任何位置抛出异常。throw 语句的操作数可以是任意表达式,表达式的结果类型决定了抛出异常的类型

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
double Div(int a, int b) throw(char, double)
{
	if (b == 0)
	{
	throw(char) 0;
	}
	if (a % b)
	{
	throw(double) b;
	}
	return (a / b);
}

捕获异常

catch 块跟在 try 块后面,用于捕获异常。可指定想要捕捉的异常类型,由 catch 关键字后括号内的异常声明类型决定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
try
{
	// 保护代码
}
catch (数据类型1 形参)
{
	// 处理异常的代码
}
catch (数据类型3 形参)
{
	// 处理异常的代码
}
catch (...)
{
	// 处理其他任何类型的代码
}

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
int a[5] = {10, 10, 8, 6, 4};
int b[5] = {5, 3, 0, 2, 0};
int n = 0, i, z;
for (i = 0; i < 5; i++)
{
	try
	{
		cout << Div(a[i], b[i]) << ", ";
		n++;
	}
    catch (char)
	{
        cout << "/0"<< ", ";
	}
	catch (double &x)
	{
		 cout << "/" << x << ", ";
	}
}
cout << endl << n << " totally" << endl;

结果

1
2
2, /3, /0, 3, /0,
2 totally