【C++初阶】第一站:C++入门基础(下)
温馨提示:这篇文章已超过430天没有更新,请注意相关的内容是否还可用!
前言:
紧接着上两篇文章,c++入门基础(上):C++入门基础(上)
c++入门基础(中):C++入门基础(中)
继续补充完c++初阶入门基础的知识点,本章知识点包括:
引用和指针的区别、内联函数、auto关键字(C++11)、基于范围的for循环(C++11)、指针空值nullptr(C++11)等补充知识。
目录
6.引用
6.6 引用和指针的区别
7.内联函数
7.1概念
7.2 特性
8.auto关键字(C++11)
8.1 类型别名思考
8.2auto简介
特别注意:auto不能推导的场景
记住关键字:typeid
9.基于范围的for循环(C++11)
9.1 范围for的语法
10. 指针空值nullptr(C++11)
6.引用
6.6 引用和指针的区别
来看下面代码,右击鼠标转到反汇编:
可以看到汇编代码,大家都是一样的,解析下面的汇编代码:
dword 双字 就是四个字节
ptr pointer缩写 即指针
[]里的数据是一个地址值,这个地址指向一个双字型数据
比如mov eax, dword ptr [a] 把内存地址a中的双字型(32位)数据赋给eax
lea表示"load effective address",表示对某个变量的地址进行加载,相当于取地址的操作。所以lea eax, [a]就是将a的地址赋给eax寄存器。
接着分别进行以下操作:
一样的转到反汇编:
引用和指针的不同点:(建议别背,从使用的角度区分)
1. 引用概念上定义一个变量的别名,指针存储一个变量地址。
2. 引用在定义时必须初始化,指针没有要求
3. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何 一个同类型实体
4. 没有NULL引用,但有NULL指针
5. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32 位平台下占4个字节)
6. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
7. 有多级指针,但是没有多级引用
8. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
9. 引用比指针使用起来相对更安全
7.内联函数
复习一下:实现一个ADD的宏函数
#define N 10
以下均为错误案例:
#define ADD(int x,int y) {return x+y;}
#define ADD( x, y) {return x+y;}
#define ADD( x, y) return x+y;
#define ADD(x,y) x+y;
#define ADD(x,y) x+y;
#define ADD(x,y) (x+y);//特别注意一下这一条为什么错误。
解析上面需要注意那条 :
从以上可以简单看出宏函数的优缺点:
缺点:
1、容易出错,语法坑很多
2、不能调试
3、没有类型安全的检查
优点:
1、没有的类型的严格限制
2、针对频繁调用小函数,不需要再建立栈帧,提高了效率
引出我们的内联函数,也是不需要建立栈帧.
7.1概念
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
如果在上述函数前增加inline关键字将其改成内联函数, 在编译期间编译器会用函数体替换函数的调用。 查看方式: 1. 在release模式下,查看编译器生成的汇编代码中是否存在 call Add 2. 在debug模式下,需要对编译器进行设置,否则不会展开 ( 因为debug模式下,编译器默认不会对代码进行优化,以下给出vs2019的设置方式 )在debug设置下默认是不会展开的:
在使用内联函数之前,需要进行以下设置:
展开是什么意思呢,就是不用调用函数,直接把函数里的功能直接拷贝放到main函数内实现:
而且解决了符号优先级的问题,因为函数传参,是把表达式算出结果再传进去的。
7.2 特性
inline是一种 以空间换时间的做法,如果编译器将函数当成内联函数处理,在 编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率 inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建 议:将 函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、 不 是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为 《C++prime》第五版关于inline的建议:
编译器视为内联函数
因代码膨胀,编译器不视为内联函数
add是内联函数,func被编译器视为不是内联函数。
把func函数类冗余的代码删除:
这样就被视作为内联了。
测试代码:
#include
#include
#include
#define ADD(x,y) ((x)+(y))
inline int add(int x, int y)
{
return x + y;
}
inline int func()
{
int x1 = 0;
int x2 = 0;
int x3 = 0;
int x4 = 0;
int ret = 0;
ret += x1;
//以下代码全注释掉
/*ret -= x2;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;
ret -= x3;*/
return 0;
}
int main()
{
ADD(1, 2);
printf("%d\n",ADD(1,2));
printf("%d\n",ADD(1,2)*3);
int a = 1, b = 2;
//ADD(a | b, a & b);//(a | b + a&b)
//int ret = add(1, 2);
int ret = add(a | b, a & b);
printf("%d\n",ret);
ret = func();
}
声明和定义分离
3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址 了,链接就会找不到
测试代码:
Func.h
#pragma once #include using namespace std; inline void f(int i); void fx();
Func.cpp
#include"Func.h"
void f(int i)
{
cout 














