C++筑器 引用生死唯一

简介: C++筑器 引用生死唯一

文章目录



C++ 引用(这篇博客是我现有知识只能这样写)

语法层和底层分开看基本没什么问题,但是一旦两个交互看就会感觉有悖论,这个有人说编译器优化,强行把细节的优化没了,反正现在凌晨3点了我头发掉没了也没悟到引发悖论的细节。用一个物理来说有点波粒二象性,有波的特性也有粒子的特性。语法层的的确确看到是别名和本体公用空间,但是底层你会发现他也是引用变量,那就是他有个双字四字节的小空间(和指针变量所占一样),我是这样理解的比如我们电脑系统不是装在硬盘里面的吗,我们开机是直接进入系统的,但实际上系统前面还有一点点的内存是存放系统信息的好像是ESP我也记不清了  ,那个东西要是没了,你系统就是废掉了,但是感觉举的例子不怎么恰当。我问过很多人,没有人说明白这个小悖论。。。烦啊。C++现在刚起步就要我头发

引用 语法层

引用概念

引用是也已存在的变量取一个别名,编译器不会为引用变量开辟内存空间(这是语法层面)它和它

引用的变量共用同一块内存空间

类型& 引用变量名(对象名) = 引用实体

引用类型必须和引用实体是同种类型的

引用特性

  1. 引用在定义时必须初始化
  2. 一个变量可以有多个引用
  3. 引用一旦引用一个实体,再不能引用其他实体

引用做参数

传值

//传值
void Swap(int x, int y)
{
  int tmp = x;
  x = y;
  y = tmp;
}
int main()
{
  int a = 0, b = 10;
  cout << a << endl << b << endl << endl;
  Swap(a, b);
  cout << a << endl << b << endl << endl;
  return 0;
}

传址

//传址
void Swap(int* x, int* y)
{
  int tmp = *x;
  *x = *y;
  *y = tmp;
}
int main()
{
  int a = 0, b = 10;
  cout << a << endl << b << endl << endl;
  Swap(&a, &b);
  cout << a << endl << b << endl << endl;
  return 0;
}

传引用

//传引用
void Swap(int& rx, int& ry)
{
  int tmp = rx;
  rx = ry;
  rx = tmp;
}
int main()
{
  int a = 0, b = 10;
  cout << a << endl << b << endl << endl;
  Swap(a, b);
  cout << a << endl << b << endl << endl;
  return 0;
}

传值、传引用效率比较

以值作为参数或者返回值类型,在传参和返回期间,函数不会直接传递实参或者将变量本身直接返回,而是传递实参或者返回变量的一份临时的拷贝,因此用值作为参数或者返回值类型,效率是非常低下的,尤其是当参数或者返回值类型非常大时,效率就更低

#include<iostream>
using namespace std;
#include <time.h>
struct A 
{ 
  int a[10000]; 
};
void TestFunc1(A a) {}
void TestFunc2(A& a) {}
void TestRefAndValue()
{
  A a;
  // 以值作为函数参数
  size_t begin1 = clock();
  for (size_t i = 0; i < 10000; ++i)
    TestFunc1(a);
  size_t end1 = clock();
  // 以引用作为函数参数
  size_t begin2 = clock();
  for (size_t i = 0; i < 10000; ++i)
    TestFunc2(a);
  size_t end2 = clock();
  // 分别计算两个函数运行结束后的时间
  cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
  cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
}
int main()
{
  TestRefAndValue();
  return 0;
}

引用做返回值

传值返回 所有的传值返回都会生成一个拷贝

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-49HdFMks-1638901936693)(C:\Users\zzy\AppData\Roaming\Typora\typora-user-images\image-20211207110234488.png)]

临时变量存在哪

1.c比较小的(4字节 8字节),是寄存器充当临时变量

2.c比较大的,临时变量是放在上一层栈中的,比如这里的Add函数的栈帧

传引用返回

错误用法

那么如何用呢

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

值和引用的作为返回值类型的性能比较

#include<iostream>
using namespace std;
#include <time.h>
struct A 
{ 
  int a[10000]; 
};
A a;
// 值返回
A TestFunc1() { return a; }
// 引用返回
A& TestFunc2() { return a; }
void TestReturnByRefOrValue()
{
  // 以值作为函数的返回值类型
  size_t begin1 = clock();
  for (size_t i = 0; i < 100000; ++i)
    TestFunc1();
  size_t end1 = clock();
  // 以引用作为函数的返回值类型
  size_t begin2 = clock();
  for (size_t i = 0; i < 100000; ++i)
    TestFunc2();
  size_t end2 = clock();
  // 计算两个函数运算完成之后的时间
  cout << "TestFunc1 time:" << end1 - begin1 << endl;
  cout << "TestFunc2 time:" << end2 - begin2 << endl;
}
int main()
{
  TestReturnByRefOrValue();
  return 0;
}

传值和指针在作为传参以及返回值类型上效率相差很大。

  1. 引用传参和返回值 有些场景下可以明显提高性能 大对象+深拷贝对象
  2. 引用传参和返回值 输出型参数和输出型返回值 人话就是函数的形参改变可以改变函数外面的实参,有些场景下,引用返回,可以改变返回对象

修改返回对象

引用的返回可读可写

#define N 10
int& fun(const int& i)
{
  static int a[N];
  return a[i];
}
int main()
{
  int i = 0;
  for (i = 0; i < N; i++)
  {
    fun(i) = 100 + i;
  }
  for (i = 0; i < N; i++)
  {
    cout << fun(i) << "  ";
  }
  return 0;
}

常引用

通过上面我们可以发现const引用大小通吃

const type& 可以接收各种类型的变量

这就引入了新的问题 const引用参数的好处

左值右值

我们经常有一种误解,即在等号左边的叫做左值(L-value),右边的叫做右值(R-value)。这个说法其实是不准确的, 首先左值右值是针对表达式来说的。C++中左值被定义为Location Value,即可以取地址的值,或者说是指表达式结束后仍然存在的值。相反右值就是临时的值


不要想着越权,越权的人是我最讨厌的人

我们假设x是个很大的对象或者是后面的深度拷贝的部分

那么我们就使用引用参数,这样是可以减少拷贝,来提高效率

假如x我们不需要改变它,我们就用const引用,来提高代码的安全性


引用 低层

我们通过vs19观察别名本体的确是在同一个地址上,所以我们说了语法上别名是没有开辟空间的,但是实际上底层实现是有空间的,因为引用是按照指针的方式来实现的。

玩底层带你看汇编这是我最喜欢看的东西

linux下面正宗汇编看不懂

引用和指针的不同点:

  1. 引用在定义时必须初始化,指针没有要求
  2. 引用在初始化时引用一个实体后,就不能再引用其他实体,而指针可以在任何时候指向任何一个同类型实体
  3. 没有NULL引用,但有NULL指针
  4. 在sizeof中含义不同:引用结果为引用类型的大小,但指针始终是地址空间所占字节个数(32位平台下占4个字节)
  5. 引用自加即引用的实体增加1,指针自加即指针向后偏移一个类型的大小
  6. 有多级指针,但是没有多级引用
  7. 访问实体方式不同,指针需要显式解引用,引用编译器自己处理
  8. 引用比指针使用起来相对更安全


目录
相关文章
|
6月前
|
存储 安全 C++
C++中的引用和指针:区别与应用
引用和指针在C++中都有其独特的优势和应用场景。引用更适合简洁、安全的代码,而指针提供了更大的灵活性和动态内存管理的能力。在实际编程中,根据需求选择适当的类型,能够编写出高效、可维护的代码。理解并正确使用这两种类型,是掌握C++编程的关键一步。
84 1
|
7月前
|
C++
C++中的const指针与const引用
C++中的const指针与const引用
99 2
|
5月前
|
存储 安全 C++
浅析C++的指针与引用
虽然指针和引用在C++中都用于间接数据访问,但它们各自拥有独特的特性和应用场景。选择使用指针还是引用,主要取决于程序的具体需求,如是否需要动态内存管理,是否希望变量可以重新指向其他对象等。理解这二者的区别,将有助于开发高效、安全的C++程序。
38 3
|
5月前
|
存储 自然语言处理 编译器
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
【C++入门 三】学习C++缺省参数 | 函数重载 | 引用
|
6月前
|
存储 安全 编译器
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
【C++航海王:追寻罗杰的编程之路】引用、内联、auto关键字、基于范围的for、指针空值nullptr
69 5
|
6月前
|
C++
C++引用
C++引用
|
6月前
|
存储 安全 编译器
【C++入门】—— C++入门 (中)_引用
【C++入门】—— C++入门 (中)_引用
40 5
|
6月前
|
C语言 C++ 编译器
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
【C++语言】冲突-C语言:输入输出、缺省参数、引用、内联函数
|
6月前
|
安全 测试技术 C++
C++中的引用
C++中的引用
36 1