“C++基础入门指南:了解语言特性和基本语法”(中)

简介: “C++基础入门指南:了解语言特性和基本语法”(中)

C++引用



引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间


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


void TestRef()
{
  int a = 10;
  int& ra = a;//<====定义引用类型
  printf("%p\n", &a);
  printf("%p\n", &ra);
}


共用了同一块内存空间

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


引用特性


1.引用必须在创建时进行初始化。


int number = 42;
int& ref = number;  // 引用初始化为变量 number


2.引用一旦引用一个实体,再不能引用其他实体
下面是一个示例说明引用在初始化后不能再引用其他实体:


int a = 42;
int b = 99;
int& ref = a;  // 引用 ref 绑定到变量 a
ref = b;       // 错误!不能重新将 ref 绑定到变量 b


一旦引用初始化完成后,它将一直与该对象关联,不能再引用其他对象。


需要注意的是,引用可以通过指针的方式进行间接更改。通过指向引用的指针,可以间接修改引用所绑定的实体,但指针本身不能再引用其他实体。


下面是一个示例说明通过指针修改引用所绑定的实体:


int a = 42;
int b = 99;
int& ref = a;       // 引用 ref 绑定到变量 a
int* ptr = &ref;    // 指针 ptr 指向引用 ref
*ptr = b;           // 通过指针间接修改引用所绑定的实体


3. 一个变量可以有多个引用


int number = 42;
int& ref1 = number;   // 第一个引用绑定到 number
int& ref2 = number;   // 第二个引用也绑定到 number


这意味着无论通过 ref1 还是 ref2 修改对象的值,实际上都是修改了同一个对象。


常引用


常引用(const reference)是指绑定到常量对象的引用。通过使用常引用,可以确保在引用的过程中,不会对被引用的对象做任何修改。


void TestConstRef()
{
    const int a = 10;
    //int& ra = a;   // 该语句编译时会出错,a为常量
    const int& ra = a;
    // int& b = 10; // 该语句编译时会出错,b为常量
    const int& b = 10;
    double d = 12.34;
    //int& rd = d; // 该语句编译时会出错,类型不同
    const int& rd = d;
}


有的同学会感到疑惑,为什么有的要加了const 才可以通过.这里要说一下权限的问题.

这里要先说一下

在引用的过程中


  1. 权限可以平移
  2. 权限可以缩小
  3. 权限不能放大


什么意思呢,下面我分别举例.


  • 权限可以平移


const int a = 0;
const int& c = a; // 权限的平移


  • 权限可以缩小


int x = 0;
const int& y = x; //权限可以缩小


  • 权限不能放大


const int a = 0;
int& b = a;// 权限的放大 error


那这样可以吗


const int a = 0;
int b = a;


答案是可以的,因为这里是赋值拷贝,b修改不影响a!


同学们在看看这个例子,这样引用正确吗


  int i = 0;
  const double& d = i;


答案也是可以的:为什么i不是直接赋值给d的,他是通过一个临时变量来交换的,而这个临时变量拥有常属性,所有接收时候必须带上const来接收.


7cc220da52984a84b81c1610d2729e47.png


举一反3,同学在来看看这题


int func()
{
  int a = 0;
  return a;
}
 int main()
 {
   //int ret& = fuc();error
   const int& ret = func(); 
 }


为什么不加const 编译不过?

答案: 其实跟上题差不多一样的道理,函数返回时候他是通过一个临时变量保存着a返回的,在这种情况下,常引用是需要的,因为临时变量的生命周期与表达式的生命周期相同,这个临时变量有着常属性,必须加上const 来接收,而const可以延长该临时变量的生命周期.通过使用常引用,将临时变量 a 的生命周期与常引用 ret 的生命周期进行了绑定.


211daf12c24f45c198d2c9411702417d.png


当然,对于较小的数据类型(如整数或指针),编译器通常会选择将其存储在寄存器中进行返回。这是为了提高返回值的效率。这种寄存器返回值的优化是由编译器自动完成的。我们无需关心.


使用场景


1. 做参数

函数可以通过引用来传递参数,不仅可以避免复制大型对象的开销,还可以修改传入的参数。


void Swap(int& left, int& right)
{
   int temp = left;
   left = right;
   right = temp;
}


2. 做返回值

函数可以返回引用类型,使得可以直接对返回值进行修改,而无需拷贝。例如:


int& Count()
{
   static int n = 0;
   n++;
   // ...
   return n;
}


下面代码输出什么结果?为什么?


int& Add(int a, int b)
{
    int c = a + b;
    return c;
}
int main()
{
    int& ret = Add(1, 2);
    Add(3, 4);
    cout << "Add(1, 2) is :"<< ret <<endl; //输出7
    return 0;
}


3f174647216d4e94b4167c4a32b3acd5.png


1.函数运行时,系统需要给该函数开辟独立的栈空间,用来保存该函数的形参、局部变量以及一些寄存器信息等

2.函数运行结束后,该函数对应的栈空间就被系统回收

3.空间被回收指该块栈空间暂时不能使用,但是内存还在;比如:上课要申请教空,上完课之后教室归还给学校,但是教室本身还在,不能说归还了之后,教室就没有了


注意:如果函数返回时,出了函数作用域,如果返回对象还在(还没还给系统),则可以使用

引用返回,如果已经还给系统了,则必须使用传值返回。

目录
打赏
0
0
0
0
1
分享
相关文章
C++入门基础2
本内容主要讲解C++中的引用、inline函数和nullptr。引用是变量的别名,与原变量共享内存,定义时需初始化且不可更改指向对象,适用于传参和返回值以提高效率;const引用可增强代码灵活性。Inline函数通过展开提高效率,但是否展开由编译器决定,不建议分离声明与定义。Nullptr用于指针赋空,取代C语言中的NULL。最后鼓励持续学习,精进技能,提升竞争力。
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
C++ 标准模板库(STL)提供了一组功能强大的容器类,用于存储和操作数据集合。不同的容器具有独特的特性和应用场景,因此选择合适的容器对于程序的性能和代码的可读性至关重要。对于刚接触 C++ 的开发者来说,了解这些容器的基础知识以及它们的特点是迈向高效编程的重要一步。本文将详细介绍 C++ 常用的容器,包括序列容器(`std::vector`、`std::array`、`std::list`、`std::deque`)、关联容器(`std::set`、`std::map`)和无序容器(`std::unordered_set`、`std::unordered_map`),全面解析它们的特点、用法
C++ 容器全面剖析:掌握 STL 的奥秘,从入门到高效编程
【C++11】新特性
`C++11`是2011年发布的`C++`重要版本,引入了约140个新特性和600个缺陷修复。其中,列表初始化(List Initialization)提供了一种更统一、更灵活和更安全的初始化方式,支持内置类型和满足特定条件的自定义类型。此外,`C++11`还引入了`auto`关键字用于自动类型推导,简化了复杂类型的声明,提高了代码的可读性和可维护性。`decltype`则用于根据表达式推导类型,增强了编译时类型检查的能力,特别适用于模板和泛型编程。
43 2
|
6月前
|
C++
C++ 20新特性之结构化绑定
在C++ 20出现之前,当我们需要访问一个结构体或类的多个成员时,通常使用.或->操作符。对于复杂的数据结构,这种访问方式往往会显得冗长,也难以理解。C++ 20中引入的结构化绑定允许我们直接从一个聚合类型(比如:tuple、struct、class等)中提取出多个成员,并为它们分别命名。这一特性大大简化了对复杂数据结构的访问方式,使代码更加清晰、易读。
83 0
【C++打怪之路Lv1】-- 入门二级
【C++打怪之路Lv1】-- 入门二级
58 0
【C++打怪之路Lv1】-- C++开篇(入门)
【C++打怪之路Lv1】-- C++开篇(入门)
64 0
类和对象(下)C++
本内容主要讲解C++中的初始化列表、类型转换、静态成员、友元、内部类、匿名对象及对象拷贝时的编译器优化。初始化列表用于成员变量定义初始化,尤其对引用、const及无默认构造函数的类类型变量至关重要。类型转换中,`explicit`可禁用隐式转换。静态成员属类而非对象,受访问限定符约束。内部类是独立类,可增强封装性。匿名对象生命周期短,常用于临时场景。编译器会优化对象拷贝以提高效率。最后,鼓励大家通过重复练习提升技能!
类和对象(中 )C++
本文详细讲解了C++中的默认成员函数,包括构造函数、析构函数、拷贝构造函数、赋值运算符重载和取地址运算符重载等内容。重点分析了各函数的特点、使用场景及相互关系,如构造函数的主要任务是初始化对象,而非创建空间;析构函数用于清理资源;拷贝构造与赋值运算符的区别在于前者用于创建新对象,后者用于已存在的对象赋值。同时,文章还探讨了运算符重载的规则及其应用场景,并通过实例加深理解。最后强调,若类中存在资源管理,需显式定义拷贝构造和赋值运算符以避免浅拷贝问题。
AI助理

你好,我是AI助理

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