【C++】入门基础(引用、inline、nullptr)

目录

一.引用

1.引用的定义

2.引用的特性

3.引用的使用场景

4.const引用

5.引用和指针的区别

二.inline

 三.nullptr


一.引用

1.引用的定义

引用不是新定义一个变量,而是给已经存在的变量取一个别名,编译器不会给引用变量开辟内存空间,它和它引用的变量共用同一块内存空间。简单来说,引用就是起别名,例如水浒传中林冲又名豹子头,这就是取别名,同时,林冲死了也就意味着豹子头死了,两者指向的都是同一个人。

用法:类型&引用别名 = 应用对象;

int main()
{
	//对a起别名b和c
	int a = 0;
	int& b = a;
	int& c = a;
	cout << a << endl;
	cout << b << endl;
	cout << c << endl;
	cout << &a << endl;
	cout << &b << endl;
	cout << &c << endl;

	return 0;
}

2.引用的特性

  1. 引用在定义的时候必须初始化。因为引用是一个别名,它的存在建立在主体存在的基础上,也就是说必须引用一个已经存在的对象,否则会引起编译报错。

  2. 一个变量可以有多个引用。正如一个人可以有多个外号,但这些引用都指向同一个对象。

  3. 引用一旦引用另一个实体,就不能再引用其他实体。引用一旦建立,就不能更改为其他实体的引用,这种“偷外号”的行为是不允许发生的。

  4. 允许引用其他引用。例如:int& b = a,int &c = b;此时就是c引用了b,但b也是引用的a,此时,b,c都是a的别名。

int a = 0;
int& b = a;
int c = 20;
//b已经引用a的情况下,不能更改为引用c
//以下直接看作赋值
b = c;
cout << a << endl;
cout << b << endl;
cout << c << endl;

3.引用的使用场景

引用在实践中主要是用于引用传参和做返回值,能够减少拷贝提高效率,同时能够改变引用对象和被引用对象。

引用传参跟指针传参的功能是类似的,但引用传参看着更简洁也更方便。例如,对于Swap函数的实现而言,引用传参可以这样实现:

void Swap(int& a, int& b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

引用返回值就要看使用场景了,例如在栈(Stack)的实现中,有一个函数叫STTop用于得到栈顶元素,返回值是int,只是一个数值的拷贝,具有常性,无法做左值,即无法进行修改。

但若返回值改为int&,那么此时就是对返回的栈顶元素取别名,那么就可以进行修改了。如下所示

typedef int STDatatype;
typedef struct Stack
{
	int* a;
	int capacity;
	int top;
}ST;

//直接引用传参
void STInit(ST& rs, int n = 4)
{
	rs.a = (STDatatype*)malloc(sizeof(STDatatype) * n);
	rs.capacity = n;
	rs.top = 0;
}

void STPush(ST& rs, STDatatype x)
{
	rs.a[rs.top] = x;
	rs.top++;
}

//int STTop(ST& rs)
//{
//	return rs.a[rs.top - 1];
//}

int& STTop(ST& rs)
{
	return rs.a[rs.top - 1];
}
int main()
{
	ST s;
	STInit(s,4);
	STPush(s, 1);
	STPush(s, 2);

	STTop(s) = 4;
	return 0;
}

4.const引用

const引用可以用来引用普通对象,普通对象是能读能写,但const引用后,引用是只读不写,注意:对象本体还是可以写的,只是引用(别名)用const修饰了不能写,这叫权限缩小

const引用也可以用来引用const对象,此时就叫权限平移,因为引用和本体的权限是相同的,都被const修饰,只能读不能写。

普通引用不能用来引用const对象,这是权限放大。原本本体就不能被修改,但引用后反而能被修改了,这合理吗?这种写法是禁止的,也会进行如下报错。

 引用临时对象需要使用const引用。什么是临时对象?临时对象出现在以下这几种情况:

类型转化:如下double类型转化为int引用

double a = 1.1;

const int& b = a;

表达式结果:如下a*3就是一个表达式,需要临时对象储存结果

int a = 1;

const int& b = a*3;

5.引用和指针的区别

  1. 引用必须初始化,指针建议初始化,但语法上不是必须的
  2. 引用不开辟空间,但指针是储存一个变量地址,需要开空间
  3. 初始化后引用不可修改指向对象,而指针可以修改指向对象
  4. 引用直接访问指向对象,指针需要解引用才能访问
  5. sizeof时,引用是引用对象类型的大小,而指针始终是地址空间所占的字节个数(32位下是4字节,64位下是8字节)
  6. 引用更加安全,指针容易出现空指针和野指针的问题

二.inline

使用inline修饰的函数就是内联函数,编译时编译器会将其在调用的地方展开,这样调用内联函数就需要建立栈帧了,可以提高效率。inline就是为了替代C语言中宏函数而实现的,宏函数实现很复杂而且容易出错,不方便调试,inline才运营而生。

当然inline对于编译器而言只是一个建议,是否展开取决于编译器本身,一般来说,inline适用于频繁调用的短小函数,对于递归函数,代码较多的函数,就算加上inline编译器也会选择忽略。

line不建议声明和定义分离到两个文件,分离会导致链接错误。但可以在同一个项目的不同源文件内定义函数名相同但实现不同的inline函数。

注:class类中的函数默认是inline

 三.nullptr

在C语言中,NULL其实是一个宏,它的定义是:

#ifndef NULL
    #ifdef __cplusplus
        #define NULL    
    #else
        #define NULL    ((void *)0)
    #endif
 #endif

 那么在使用时就会产生歧义,例如在调用空值的指针时,就有可能调用到int类型的重载函数,例如:

void f(int x)
{
	cout << "f(int x)" << endl;
}
void f(int* x)
{
	cout << "f(int* x)" << endl;
}
int main()
{
	f(0);
	f(NULL);
	return 0;
}

//结果是两次都是调用的f(int x)

因此在C++11中引入了nullptr,这是一个特殊的关键字,它可以转化为任意类型的其他指针类型,但不能转化为整数类型,这就避免上图的出错。 

看到这里,就能对有了一定的C++基础知识,但还不算入门,接下里我会持续更新类和对象的内容,那才是面向对象编程的精髓。感谢观看,欢迎关注。 

相关推荐

  1. [C++ 入门基础 - 引用]

    2024-07-15 08:20:03       21 阅读
  2. C++基础入门(命名空间,函数,引用

    2024-07-15 08:20:03       43 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-15 08:20:03       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-15 08:20:03       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-15 08:20:03       58 阅读
  4. Python语言-面向对象

    2024-07-15 08:20:03       69 阅读

热门阅读

  1. python分析PDF文件信息常用的功能模块

    2024-07-15 08:20:03       21 阅读
  2. markdown文件转pdf

    2024-07-15 08:20:03       23 阅读
  3. 自己为什么跑步?

    2024-07-15 08:20:03       28 阅读
  4. LightDM和SDDM显示管理器学习小知识

    2024-07-15 08:20:03       21 阅读
  5. Mybatis

    Mybatis

    2024-07-15 08:20:03      20 阅读
  6. AI学习指南机器学习篇-高斯混合模型

    2024-07-15 08:20:03       22 阅读
  7. 使用 Dubbo 的 XML 配置

    2024-07-15 08:20:03       20 阅读
  8. 阿里新开源GPU版本的FunASR安装避坑

    2024-07-15 08:20:03       25 阅读