学习笔记 C++学习整理

写在卸载之前

其实C++这门计算机语言目前只能说会也就是入门 但是不能说精通

所以最近会学一些东西然后不定期整理上去

允许我夹带一波私货

正式开始

1.oct,hex,dec

ta们伴随cout分别输出八进制,十六进制,十进制

#include<bits/stdc++.h>
using namespace std;
int d=99999;
int main()
{
	cout<<oct<<d<<endl;//输出八进制 
	cout<<hex<<d<<endl;//输出十六进制 
	cout<<dec<<d<<endl;//输出十进制
	cout<<bitset<sizeof(d)*8>(d)<<endl;//凭借bitset输出二进制 
}

Output

303237
1869f
99999
00000000000000011000011010011111

2.关键字auto

对于变量的自动识别

#include<iostream>
using namespace std;
int main()
{
  auto Flag=1;
  
  cout<<"Flag = "<<Flag;
  cout<<" , sizeof(Flag)= "<<sizeof(Flag)<<endl;
  
  auto FLAG=true; 
  cout<<"FLAG = "<<FLAG;
  cout<<" , sizeof(FLAG)= "<<sizeof(FLAG)<<endl;
  
  auto NumBer=1000000000000;
  
  cout<<"NumBer = "<<NumBer;
  cout<<" , sizeof(NumBer)= "<<sizeof(NumBer)<<endl; 
  return 0;
}

Output

Flag = 1 , sizeof(Flag)= 4
FLAG = 1 , sizeof(FLAG)= 1
NumBer = 1000000000000 , sizeof(NumBer)= 8

乍一看没有什么了不起 但是在变量类型十分复杂的时候 会让变成容易很多

比如说 我们定义并访问一个vector

vector<int> G;
for(vector<int>::iterator it=G.begin();it<G.end();++it)

我们觉得直接写vector::iterator实在是太麻烦了 所以直接使用auto代替

vector<int> G;
for(auto it=G.begin();it<G.end();++it);

3.存储指针的内存

不管指针指向什么类型的数据 指针所占用的内存单元都相同 都是4字节

4.关键字const用于指针

1) 指针指向的数据为常量不能修改 但是可以修改包含的地址

也就是不能通过指针去修改其所指向的数据

int d=12;
const int* p=&d;//如何定义

*p=13;//这是错误的 不可以修改指向的数据

int dx=13;
p=&dx;//这是正确的 可以修改包含的地址

2) 指针包含的地址为常量不能修改 但是可以修改指向的数据

int d=12;
int* const p=&d;//如何定义

*p=13;//这是正确的 可以修改指向的数据

int dx=13;
p=&dx;//这是错误的 不可以修改包含的地址

3) 指针包含的地址,指向的数据均为常量不能修改 这是最严格的组合

int d=12;
const int* const p=&d;//如何定义

*p=13;//错误

int dx=13;
p=&dx;//错误

这么写的好处是 使用函数传递指针的时候 可以防止函数修改其所指向的值 使得函数更容易维护

5.try,throw,catch异常处理

[【参考出处】](http://c.biancheng.net/view/422.html)

对于程序来说 如果出现的异常了怎么办

1.指针动态内存申请时超出限制
2.数组越界
3.a/b时b=0
4.文件读取时文件不存在

这个时候出现了 try,throw,catch语句

try语句内部运行的时候 通过if-else判断是否出现了人为的异常情况

如果出现了 就通过throw语句抛出异常(注:这里的throw有break的功效 也就是一旦throw了就不会在执行try中之后的语句)

然后catch通过判断异常的类型 输出异常的情况

同样 并列catch也具有优先性 也就是哪个先get到了异常 哪个就先执行 而后面的catch都不会再get异常并执行

#include<bits/stdc++.h>
using namespace std;
int n,m;
int main()
{
	cin>>n>>m;
	try
	{
		cout<<"before dividing."<<endl;
		if(n==0) throw -1;
		else if(m==0) throw -1.0;
		else cout<<"n/m="<<n/m<<endl;
		cout<<"correctly!"<<endl;
	}
	catch(int d)
	{
		cout<<"n==0 "<<d<<endl; 
	}
	catch(double e)
	{
		cout<<"m==0 "<<e<<endl;
	}
	catch(...)//这个catch语句可以get所有类型的异常 但是由于上面所说的catch的优先性 所以必须放在最后
	{
		cout<<"all catch!"<<endl;
	}
	cout<<"finished!"<<endl;
	return 0;
}

Sample

Input
6 3
Output
n/m=2
correctly!
finished!

Input
3 0
Output
m==0 -1
finished!

Input
0 4
Output
n==0 -1
finished!

对于一个函数来说 如果当前的异常没有在其内部被get到的话 那么这个异常就会回馈到调用ta的函数 一般称之为上一层函数 直到回馈到main函数

这里就不细说了

6.空间申请时new的变种--new(nothrow)

我们将new替换为new(nothrow) 如果内存超过限制的话 会将申请空间的指针自动转换为空指针NULL

7.引用

“你们抓周树人,跟我鲁迅有什么关系?”

这句话听上去很好笑 但是实际上在程序设计中确实存在

int a;
int b;
b=a;

我们修改b 确实跟a没有什么关系

但是

int a;
int& b=a;

这样的话 就构成了引用 我们修改b也就是在修改a

引用的作用很大

比如说在函数中

returntype function(Type Name);
Result=function(x);

这里等于是将x复制给了Name 如果x占用内存较大 那么复制开销也很大

但是如果使用引用的话 就避免了这份开销

另外 使用引用的话 每一次定义就相当于别名 所以你抓了周树人也就等于抓走了鲁迅

当然了 由于指针存在const防止函数修改 引用也可以通过添加const防止修改

一般来讲 对于内部参数为指针或者引用的函数 推荐后者 因为指针可能会无效 而且引用更简单

上一篇:带你用汇编写循序


下一篇:「汇编语言 第 3 版 王爽」- 参考答案:课程设计 1 @20210212