哈喽,今天是我重生的第二天,今天我学习了c++的引用、auto关键字、内联函数、范围for。
目录
一.引用
#include<iostream>
using namespace std;
int main()
{
int a = 2;
int& b = a;//b就是是a的引用
return 0;
}
从引用的定义来看,引用是变量的一个别名,和它所引用的变量共用一块内存空间。
因此,当b++时,a的也将发生改变。
b++;
cout << a << endl;
a的值为以下运行结果
我们可以总结:变量的引用可以直接访问这个变量在内存中的空间。进而通过引用直接改变这个变量的值。而在C语言中,要想改变变量的值,就是使用指针,变量的指针就是变量的地址,可以通过这个变量的地址解引用改变这个变量。
#include<stdio.h>
int main()
{
int a = 2;
int* b = &a;//指针存储a的地址
(*b)++;
printf("%d", a);
return 0;
}
由此可知,引用和一级指针都可以改变变量的值。
那我们就可以举一反三的知道:一级指针的引用和二级指针都可以改变一级指针。
#include<iostream>
using namespace std;
int main()
{
int& a;//a未初始化,不合法
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int a = 2;
int& b = a;//a的三个引用b、c、d
int& c = a;
int& d = b;//引用的引用指向的还是同一内存空间
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
return 0;
}
#include<iostream>
using namespace std;
int main()
{
int a = 2;
int x = 3;
int& b = a;//a的引用
b = x;//a的引用无法修改,这句代码含义是赋值:a=3
return 0;
}
引用的使用场景
一.传参
当我们要写两个整型的交换函数时,只能将形参写成一级指针的形式,通过指针来交换两变量的值,当有了引用后,也可以将引用作为形参,通过引用交换两个变量。这里体现了一级指针和引用的相同作用。只不过引用的使用更加简单明了。
void Swap(int& left, int& right)
{
int temp = left;
left = right;
right = temp;
}
在数据结构阶段,单链表的头插函数是这样写的
void PushHead(struct ListNode** pphead,int n)
{
//创建新节点
struct ListNode* newnode=(struct ListNode*)malloc(sizeof(struct ListNode));
newnode->date=n;
//链接新节点
newnode->next=*pphead;
*pphead=newnode;
}
在这里,要想改变链表的头节点指针,就需要用到二级指针。用引用同样可以做到
void PushHead(struct ListNode*& phead,int n)
{
//创建新节点
struct ListNode* newnode=(struct ListNode*)malloc(sizeof(struct ListNode));
newnode->date=n;
//链接新节点
newnode->next=phead;
phead=newnode;
}
体现了二级指针和一级指针的引用相同的作用。
二.做返回值
引用做返回值,可以通过函数返回函数内对象的引用来在函数外修改这个对象。
#include<iostream>
#include<assert.h>
using namespace std;
struct sequence
{
int* a;
int size;
int capcity;
};
int& SearchModify(sequence* seq,int pos)//查找pos下标位置的数据并修改
{
assert(pos < seq->size);
return seq->a[pos];
}
可以查找
struct sequence s;
int x=SearchModify(&s, 2);//查找下标为2位置的值
可以修改
SearchModify(&s, 2) = 3;//修改下标为2位置的值为3
#include<iostream>
using namespace std;
int& func()
{
int n = 2;//n是局部变量,出函数将销毁
n++;
return n;//但是返回了n的引用,让函数外可以找到已经销毁的空间
}
int main()
{
int& a = func();//a这块空间是非法的
return 0;
}
可以修改代码使正确。
stactic int n=2;//静态变量,出作用域不销毁
二.auto关键字
#include<iostream>
using namespace std;
int main()
{
auto a = 3;//int
auto b = 2.7;//double
auto c = 'm';//char
auto s = "ssacs";//string
auto a = &a;//注意:auto与auto*没有区别
auto* b = &a;
auto& c = a;//引用必须auto&
return 0;
}
注意:auto类型不能用来做形参,不能用来声明数组。
三.内联函数
// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
f(10);
return 0;
}
// 链接错误:main.obj : error LNK2019: 无法解析的外部符号 "void __cdecl
//f(int)" (?f@@YAXH@Z),该符号在函数 _main 中被引用
四.范围for
#include<iostream>
using namespace std;
int main()
{
int arr [] = {1,2,3,4,5};
//遍历数组
for (int n : arr)
{
cout << n << " ";
}
return 0;
}
由于范围for的第一个参数是用于迭代的变量,要想改变数组内的值就不能直接改变这个变量的值。例如
#include<iostream>
using namespace std;
int main()
{
int arr [] = {1,2,3,4,5};
//遍历数组
for (int n : arr)//打印数组
{
cout << n << " ";
}
cout << endl;
for (int n : arr)//数组元素全部*2
{
n*=2;
}
for (int n : arr)//打印数组
{
cout << n << " ";
}
return 0;
}
正确的方法是:使用引用做用于迭代的变量,因为数组的值会依次赋值给引用,就顺便得到了数组全部元素的引用。进而用每个元素的引用改变数组元素。
for (int& n : arr)//数组元素全部*2
{
n*=2;
}