重生之我要学C++第二天

简介: 重生之我要学C++第二天

一.引用

定义:引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空 间,它和它引用的变量共用同一块内存空间。是C++基于C语言指针的概念新增加的概念,底层实现是依靠指针。

接下来通过代码来见识下引用

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  int a = 2;
6.  int& b = a;//b就是是a的引用
7.  return 0;
8. }

从引用的定义来看,引用是变量的一个别名,和它所引用的变量共用一块内存空间。

因此,当b++时,a的也将发生改变。

1.     b++;
2.  cout << a << endl;

a的值为以下运行结果

我们可以总结:变量的引用可以直接访问这个变量在内存中的空间。进而通过引用直接改变这个变量的值。而在C语言中,要想改变变量的值,就是使用指针,变量的指针就是变量的地址,可以通过这个变量的地址解引用改变这个变量。

1. #include<stdio.h>
2. int main()
3. {
4.  int a = 2;
5.  int* b = &a;//指针存储a的地址
6.  (*b)++;
7.  printf("%d", a);
8.  return 0;
9. }

由此可知,引用一级指针都可以改变变量的值

那我们就可以举一反三的知道:一级指针的引用二级指针都可以改变一级指针

C++引用特性

1. 引用在定义时必须初始化

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  int& a;//a未初始化,不合法
6.  return 0;
7. }

2. 一个变量可以有多个引用,引用的引用指向的还是同一内存空间。

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  int a = 2;
6.  int& b = a;//a的三个引用b、c、d
7.  int& c = a;
8.  int& d = b;//引用的引用指向的还是同一内存空间
9.  cout << &a << endl;
10.   cout << &b << endl;
11.   cout << &c << endl;
12.   cout << &d << endl;
13.   return 0;
14. }

3. 引用一旦引用一个实体,再不能引用其他实体

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  int a = 2;
6.  int x = 3;
7.  int& b = a;//a的引用
8.  b = x;//a的引用无法修改,这句代码含义是赋值:a=3
9.  return 0;
10. }

引用的使用场景

一.传参

当我们要写两个整型的交换函数时,只能将形参写成一级指针的形式,通过指针来交换两变量的值,当有了引用后,也可以将引用作为形参,通过引用交换两个变量。这里体现了一级指针和引用的相同作用。只不过引用的使用更加简单明了。

1. void Swap(int& left, int& right)
2. {
3.   int temp = left;
4.    left = right;
5.    right = temp;
6. }

在数据结构阶段,单链表的头插函数是这样写的

1. void PushHead(struct ListNode** pphead,int n)
2. {
3. //创建新节点
4. struct ListNode* newnode=(struct ListNode*)malloc(sizeof(struct ListNode));
5.     newnode->date=n;
6. //链接新节点
7.     newnode->next=*pphead;
8.     *pphead=newnode;
9. }

在这里,要想改变链表的头节点指针,就需要用到二级指针。用引用同样可以做到

1. void PushHead(struct ListNode*& phead,int n)
2. {
3. //创建新节点
4. struct ListNode* newnode=(struct ListNode*)malloc(sizeof(struct ListNode));
5.     newnode->date=n;
6. //链接新节点
7.     newnode->next=phead;
8.     phead=newnode;
9. }

体现了二级指针和一级指针的引用相同的作用。

二.做返回值

引用做返回值,可以通过函数返回函数内对象的引用来在函数外修改这个对象。

1. #include<iostream>
2. #include<assert.h>
3. using namespace std;
4. struct sequence
5. {
6.  int* a;
7.  int size;
8.  int capcity;
9. };
10. int& SearchModify(sequence* seq,int pos)//查找pos下标位置的数据并修改
11. {
12.   assert(pos < seq->size);
13.   return seq->a[pos];
14. }

可以查找

1. struct sequence s;
2. int x=SearchModify(&s, 2);//查找下标为2位置的值

可以修改

SearchModify(&s, 2) = 3;//修改下标为2位置的值为3

注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用引用返回,如果已经还给系统了,则必须使用传值返回。

1. #include<iostream>
2. using namespace std;
3. int& func()
4. {
5.  int n = 2;//n是局部变量,出函数将销毁
6.  n++;
7.  return n;//但是返回了n的引用,让函数外可以找到已经销毁的空间
8. }
9. int main()
10. {
11.   int& a = func();//a这块空间是非法的
12.   return 0;
13. }

可以修改代码使正确。

stactic int n=2;//静态变量,出作用域不销毁

二.auto关键字

随着程序越来越复杂,程序中用到的类型也越来越复杂,经常体现在:

1. 类型难于拼写

2. 含义不明确导致容易出错

使用auto定义变量时必须对其进行初始化,在编译阶段编译器需要根据初始化表达式来推导auto的实际类型。因此auto并非是一种类型的声明,而是一个类型声明时的占位符,编译器在编译期会将auto替换为变量实际的类型

auto会自动识别类型:

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  auto a = 3;//int
6.  auto b = 2.7;//double
7.  auto c = 'm';//char
8.  auto s = "ssacs";//string
9.    auto a = &a;//注意:auto与auto*没有区别
10.    auto* b = &a;
11.    auto& c = a;//引用必须auto&
12.   return 0;
13. }

注意:auto类型不能用来做形参,不能用来声明数组。

三.内联函数

概念 :以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调 用建立栈帧的开销,内联函数提升程序运行的效率。

特性:

1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。

2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)是递归、且频繁调用的函数采用inline修饰,否则编译器会忽视inline特性。

3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。建议将inline声明定义都放到.h文件中。

1. // F.h
2. #include <iostream>
3. using namespace std;
4. inline void f(int i);
5. // F.cpp
6. #include "F.h"
7. void f(int i)
8. {
9.  cout << i << endl;
10. }
11. // main.cpp
12. #include "F.h"
13. int main()
14. {
15. f(10);
16. return 0;
17. }
18. // 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl 
19. //f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用

四.范围for

对于一个有范围的集合而言,由程序员来说明循环的范围是多余的,有时候还会容易犯错误。因此C++11中引入了基于范围的for循环。for循环后的括号由冒号分为两部分:第一部分是范围内用于迭代的变量,第二部分则表示被迭代的范围

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  int arr [] = {1,2,3,4,5};
6.  //遍历数组
7.  for (int n : arr)
8.  {
9.    cout << n << " ";
10.   }
11.   return 0;
12. }

由于范围for的第一个参数是用于迭代的变量,要想改变数组内的值就不能直接改变这个变量的值。例如

1. #include<iostream>
2. using namespace std;
3. int main()
4. {
5.  int arr [] = {1,2,3,4,5};
6.  //遍历数组
7.  for (int n : arr)//打印数组
8.  {
9.    cout << n << " ";
10.   }
11.   cout << endl;
12.   for (int n : arr)//数组元素全部*2
13.   {
14.     n*=2;
15.   }
16. 
17.   for (int n : arr)//打印数组
18.   {
19.     cout << n << " ";
20.   }
21.   return 0;
22. }

正确的方法是:使用引用做用于迭代的变量,因为数组的值会依次赋值给引用,就顺便得到了数组全部元素的引用。进而用每个元素的引用改变数组元素。

1. for (int& n : arr)//数组元素全部*2
2. {
3.  n*=2;
4. }

相关文章
重生之我要学C++第六天(const,static,友元)
重生之我要学C++第六天(const,static,友元)
157 0
重生之我要学C++第五天(下)
重生之我要学C++第五天(下)
129 0
重生之我要学C++第五天(上)
重生之我要学C++第五天(上)
156 0
重生之我要学C++第三天(类和对象)
重生之我要学C++第三天(类和对象)
110 0
重生之我要学C++第一天
重生之我要学C++第一天
179 0
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
44 0
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
112 0
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
114 12
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等

登录插画

登录以查看您的控制台资源

管理云资源
状态一览
快捷访问