[Cherno C++ 笔记 P11~P20]判断,循环,指针,引用,类

系列博客

[Cherno C++ 笔记 P1~P10]安装、链接器、变量、函数、头文件
[Cherno C++ 笔记 P11~P20]判断,循环,指针,引用,类
[Cherno C++ 笔记 P21~P30]static,枚举,构造函数,析构函数,继承,虚函数,接口,可见性
[Cherno C++ 笔记 P31~P40]数组、字符串、CONST、mutable、成员初始化列表、三元操作符、创建初始化对象、new关键字、隐式转换与explicit
[Cherno C++ 笔记 P41~P50]运算符重载、this、生存期、智能指针、复制与拷贝构造函数、箭头操作符、动态数组、std::vector、静态链接、动态库

前言

这个系列的视频需要一些基础,最好是学过C。

视频链接

P11 如何在Visual Studio中调试代码
P12 C++条件与分支(if语句)
P13 Visual Studio的最佳设置
P14 C++循环(for 、while)
P15 C++控制流语句(continue, break, return)
P16 C++指针
P17 C++引用
P18 C++类
P19 C++类与结构体对比
P20 如何写一个C++类

P11 如何在Visual Studio中调试代码

P12 C++条件与分支(if语句)

if else

让我们写一个简单的if else

#include<iostream>

int main() 
{
	int a = 5;
	if (a < 5)
	{
		std::cout << a << std::endl;
	}
	else
	{
		std::cout << a << std::endl;
	}

	std::cin.get();
}

汇编中的if else

让我们先来看一下比较语句所产生的汇编
比较语句产生的汇编
当然,我们可以通过 逐语句 运行来查看这些语句的执行过程
我们也可以比较<、>、==、>=、<=之间的差别

接下来我们可以来看看if else产生的汇编
if else产生的汇编
大括号之间的东西我们大可不必关心,如果不在大括号中写点什么的话,这里的if else是不会产生汇编语句的。

我们需要关心的是其中的跳转语句。
可以看到,如果比较不成功的话,我们会直接跳转到else大括号中的第一行0FB1ED8.这里else并没有产生什么汇编语句,产生汇编语句的是else大括号中的代码。
如果比较成功,在运行完if下的语句后,我们会看到有一个jmp跳转,跳过else中的内容。

我们知道bool中0为False,其他为True,所以我们可以这么写。
bool
je的功能是当值为0时进行跳转。
这样我们就来根据一个指针是否为空来进行相应的操作
指针
可以看到,同样产生了je指令。

P13 Visual Studio的最佳设置

P14 C++循环(for 、while)

for,while,do while

让我们简单的来写一下这几种循环

#include<iostream>

int main() 
{
	int a = 0;
	for (int i = 0; i < 5; i++)
	{
		a++;
	}

	while (a<10)
	{
		a++;
	}

	do
	{
		a++;
	} while (a<20);

	std::cout << a << std::endl;

	std::cin.get();
}
汇编中的循环

for循环
我们可以通过逐行执行来观察,for的执行顺序是 E7C >E83>E8E>E92,在这里执行判断,如果比较成功,接着往下>E94>E97>E9A>E9D>E85>E88>E8B,在这里进行+1的操作后,接着往下>E8E…实现循环。

我们再来比较一下while 和 do while
while
do while
我们可以看到这些循环实现原理都是一样的。
这几种循环可以相互替换,如何使用看个人习惯。
我个人的习惯是:有明确循环次数时使用for,没有明确循环次数时使用while

P15 C++控制流语句(continue, break, return)

我们来简单写一下

#include<iostream>

int func(int a)
{
	for (int i = 0; i < 10; i++)
	{
		if (a++ % 3 == 0)
		{
			std::cout << a << std::endl;
		}
		else
		{
			continue;
		}

		if (a++ < 10)
		{
			break;
		}
	}
	return a;
}


int main() 
{
	int x = 0;
	
	std::cout << func(x) << std::endl;

	std::cin.get();
}

汇编中的break,continue,return

我们来看一下主要部分

	for (int i = 0; i < 10; i++)
00F65F95  mov         dword ptr [ebp-8],0  
00F65F9C  jmp         __$EncStackInitStart+2Bh (0F65FA7h)  
00F65F9E  mov         eax,dword ptr [ebp-8]  
00F65FA1  add         eax,1  
00F65FA4  mov         dword ptr [ebp-8],eax  
00F65FA7  cmp         dword ptr [ebp-8],0Ah  
00F65FAB  jge         __$EncStackInitStart+0EEh (0F6606Ah)  
	{
		if (a++ % 3 == 0)
00F65FB1  mov         eax,dword ptr [a]  
00F65FB4  cdq  
00F65FB5  mov         ecx,3  
00F65FBA  idiv        eax,ecx  
00F65FBC  mov         dword ptr [ebp-0D0h],edx  
00F65FC2  mov         edx,dword ptr [a]  
00F65FC5  add         edx,1  
00F65FC8  mov         dword ptr [a],edx  
00F65FCB  cmp         dword ptr [ebp-0D0h],0  
00F65FD2  jne         __$EncStackInitStart+64h (0F65FE0h)  
00F65FD4  mov         dword ptr [ebp-0D4h],1  
00F65FDE  jmp         __$EncStackInitStart+6Eh (0F65FEAh)  
00F65FE0  mov         dword ptr [ebp-0D4h],0  
00F65FEA  cmp         dword ptr [ebp-0D4h],0  
00F65FF1  je          __$EncStackInitStart+0A8h (0F66024h)  
		{
			std::cout << a << std::endl;
00F65FF3  mov         esi,esp  
00F65FF5  push        offset std::endl<char,std::char_traits<char> > (0F6103Ch)  
00F65FFA  mov         edi,esp  
00F65FFC  mov         eax,dword ptr [a]  
00F65FFF  push        eax  
00F66000  mov         ecx,dword ptr [__imp_std::cout (0F6D0DCh)]  
00F66006  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0F6D0E4h)]  
00F6600C  cmp         edi,esp  
00F6600E  call        __RTC_CheckEsp (0F61294h)  
00F66013  mov         ecx,eax  
00F66015  call        dword ptr [__imp_std::basic_ostream<char,std::char_traits<char> >::operator<< (0F6D0A0h)]  
00F6601B  cmp         esi,esp  
00F6601D  call        __RTC_CheckEsp (0F61294h)  
		}
00F66022  jmp         __$EncStackInitStart+0ADh (0F66029h)  
		else
		{
			continue;
00F66024  jmp         __$EncStackInitStart+22h (0F65F9Eh)  
		}

		if (a++ < 10)
00F66029  mov         eax,dword ptr [a]  
00F6602C  mov         dword ptr [ebp-0D0h],eax  
00F66032  mov         ecx,dword ptr [a]  
00F66035  add         ecx,1  
00F66038  mov         dword ptr [a],ecx  
00F6603B  cmp         dword ptr [ebp-0D0h],0Ah  
00F66042  jge         __$EncStackInitStart+0D4h (0F66050h)  
00F66044  mov         dword ptr [ebp-0D4h],1  
00F6604E  jmp         __$EncStackInitStart+0DEh (0F6605Ah)  
00F66050  mov         dword ptr [ebp-0D4h],0  
00F6605A  cmp         dword ptr [ebp-0D4h],0  
00F66061  je          __$EncStackInitStart+0E9h (0F66065h)  
		{
			break;
00F66063  jmp         __$EncStackInitStart+0EEh (0F6606Ah)  
		}
	}
00F66065  jmp         __$EncStackInitStart+22h (0F65F9Eh)  
	return a;
00F6606A  mov         eax,dword ptr [a]  
}
00F6606D  pop         edi  
00F6606E  pop         esi  
00F6606F  pop         ebx  
00F66070  add         esp,0D4h  
00F66076  cmp         ebp,esp  
00F66078  call        __RTC_CheckEsp (0F61294h)  
00F6607D  mov         esp,ebp  
00F6607F  pop         ebp  
00F66080  ret  

这样我们可以清楚的看到break、continue、return的工作原理。

P16 C++指针

什么是指针

指针是一个整数,一种存储内存地址的数字。
所有类型的指针都是保存内存地址的整数。
所有类型的指针都是保存内存地址的整数。
所有类型的指针都是保存内存地址的整数。

我们来创建一个空指针瞅一瞅
void* ptr = 0;,这是一个空指针,它没有任何类型。当然,我们也可以用NULL来创建,NULL
这样我们就创建了一个没有用的空指针。

让我们给它一个值

	int a = 5;
	void* ptr = &a;

我们给他打个断点来看看
变量中的值
ptr的值是以十六进制显示出来的一个整数,这个指针现在保存的就是a的内存地址
让我们在内存中看一看
查看内存中的东西
我们把ptr的值复制过去看看
内存中的值
可以看到这里的值为5

我们把指针的类型改成long long

	int a = 5;
	long long* ptr = (long long*)&a;

内存中的值
我们可以看到,这里的值仍然是5

P17 C++引用

	int a = 5;
	int& ref = a;

ref这个变量实际上并不存在,它可以看作是变量a的别名。对ref进行操作实际上是对a操作。
当设置完成以后,不能再改变它引用的东西。

P18 C++类

一个简单的类
class Player 
{
public:
	int x, y;
	int speed;

	void Move(int xa,int ya) 
	{
		x += xa * speed;
		y += ya * speed;
	}
};

类允许我们将变量分组到一个类型中,并为这些变量添加功能。

类并没有为变量提供什么新功能,不能用一般代码完成的工作用类同样无法完成。类只是提高了我们维护代码的效率。

P19 C++类与结构体对比

class 和 struct
class Player 
{
	int x, y;
};

struct MyStruct
{
	int x, y;
}; 

结构体和类基本上没有什么区别,只有一个关于可见度的小区别,class中默认为private,而struct中默认为public。
C++中存在结构体的原因是为了与C保持向后兼容性。

P20 如何写一个C++类

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值