首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

详解C++中引用传递的概念;C++类中的引用成员为什么初始化后就不能更改了?

  • 25-03-05 03:40
  • 2029
  • 7667
blog.csdn.net

在看这篇文章看可以看下我之前写的关于C++中参数的引用传递的介绍,详情见 http://iyenn.com/rec/1709396.html

目录

  • 01-引用传递本质上是利用指针进行的操作
    • 1. **引用的本质**
    • 2. **引用传递的定义**
      • 普通变量的引用定义
      • 函数返回值为引用类型的定义
    • 3. **函数中引用传递的本质**
    • 4. **引用与指针的区别**
    • 5. **引用传递的优点**
    • 6. **总结**
  • 02-C++类中的引用成员为什么初始化后就不能更改了?

01-引用传递本质上是利用指针进行的操作

引用传递在本质上是通过指针来实现的,但引用和指针在语法和使用上有明显的区别。以下是详细分析:


1. 引用的本质

在 C++ 中,引用是变量的别名,实际上是对别的变量的一种绑定操作,这种绑定操作一旦建立,不可更改,引用的底层实现通常是通过指针来完成的。编译器会将引用转换为指针操作,但在语法层面,引用更直观和安全。

例如,以下代码:

int x = 10;
int &ref = x;
ref = 20; // 修改x的值
  • 1
  • 2
  • 3

在底层可能会被编译器转换为:

int x = 10;
int *ptr = &x; // 引用被转换为指针
*ptr = 20;     // 通过指针修改x的值
  • 1
  • 2
  • 3

另外,由于对别的变量的绑定操作一旦建立,则不可更改,所以,如果在后面增加代码:

int y = 30;
ref = y;
  • 1
  • 2

那么ref不会重新绑定到y,而是会将 y 的值赋给x,所以下面的代码执行完后:

int x = 10;
int &ref = x;
ref = 20; // 修改x的值
int y = 30;
ref = y;
ref = 40;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

x的值为40,ref仍然是与x绑定,而不是改绑为y,y的值仍然为30。

上面这段代码带详细注释的版本如下:

int x = 10;      // x 初始化为 10
int &ref = x;    // ref 是 x 的引用,ref 和 x 绑定到同一个内存地址
ref = 20;        // 修改 ref 也就是修改 x,现在 x 的值为 20

int y = 30;      // y 初始化为 30
ref = y;         // 将 y 的值赋给 ref 所引用的变量 x,x 的值变为 30

ref = 40;        // 修改 ref 也就是修改 x,x 的值变为 40
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2. 引用传递的定义

普通变量的引用定义

int &a = x;  // 正确:引用 a 绑定到 x
int& b = y;  // 也正确:b 绑定到 y
  • 1
  • 2

函数返回值为引用类型的定义

示例1:

int globalValue = 10;  // 定义一个全局变量

// 函数返回 int 的引用
int& func() {
    return globalValue;  // 返回int类型全局变量的引用
}

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

注意:函数的返回值为引用类型时,符号&与类型名不能分开写,即int& func() {}你不能写成int & func() {}

示例2:

    MyClass& setValue(int v) {
        value = v;
        return *this; // 返回当前对象的引用,注意this是MyClass类型对象的指针。
    }
  • 1
  • 2
  • 3
  • 4

注意:函数的返回值为引用类型时,符号&与类型名不能分开写,即int& func() {}你不能写成int & func() {}
为了更好的理解示例2,我把示例2的完整代码给出来:

class MyClass {
private:
    int value;
public:
    MyClass& setValue(int v) {
        value = v;
        return *this; // 返回当前对象的引用
    }

    void show() {
        std::cout << "Value: " << value << std::endl;
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

关于关键词this的详细介绍见:http://iyenn.com/rec/1709318.html

3. 函数中引用传递的本质

引用传递的本质也是通过指针实现的。例如:

void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5

在底层可能会被编译器转换为:

void swap(int *a, int *b) {
    int temp = *a;
    *a = *b;
    *b = temp;
}
  • 1
  • 2
  • 3
  • 4
  • 5

调用时:

swap(x, y);
  • 1

会被转换为:

swap(&x, &y);
  • 1

4. 引用与指针的区别

虽然引用在底层是通过指针实现的,但它们在语法和使用上有以下区别:

特性引用 (&)指针 (*)
初始化必须在声明时初始化,且不能更改引用对象可以不初始化,也可以随时指向其他对象
空值不能为空(必须绑定到一个有效对象)可以为空(nullptr 或 NULL)
语法直接使用变量名,无需解引用需要使用 * 解引用
安全性更安全,避免了空指针和野指针问题需要手动检查空指针和野指针
用途通常用于函数参数传递和返回值优化更灵活,适用于动态内存管理等场景

5. 引用传递的优点

引用传递在 C++ 中被广泛使用,主要因为它有以下优点:

  1. 语法简洁:不需要显式使用 * 和 & 操作符。
  2. 安全性高:引用不能为空,避免了空指针问题。
  3. 可读性强:代码更直观,易于理解。

例如:

void print(int &value) {
    cout << value << endl;
}
  • 1
  • 2
  • 3

比以下指针版本更简洁:

void print(int *value) {
    if (value != nullptr) {
        cout << *value << endl;
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5

6. 总结

  • 引用传递在底层是通过指针实现的,但引用提供了更高级的抽象,使代码更简洁和安全。
  • 引用和指针各有优缺点,选择使用哪种方式取决于具体场景:
    • 如果需要更安全和简洁的语法,优先使用引用。
    • 如果需要更灵活的操作(如动态内存管理),则使用指针。

02-C++类中的引用成员为什么初始化后就不能更改了?

因为 C++ 规定:

  • 所有成员变量必须在对象构造完成前初始化。
  • 成员函数的执行发生在对象构造完成之后。
  • 上面我已经说了,C++ 的引用本质上是别名,一旦绑定到某个对象,就无法更改绑定。因此,引用类型的成员变量必须在对象构造时就初始化,否则无法保证其正确性。

一个错误示例如下:

class Example {
private:
    int& ref;  // 引用成员

public:
    void init(int& r) {
        ref = r;  // ❌ 错误!引用已经初始化,不能再更改绑定
    }
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

上面的错误示例更正后的代码如下:

class Example {
private:
    int& ref;

public:
    Example(int& r) : ref(r) {}  // ✅ 正确,初始化列表中完成绑定
};

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

关于C++的初始化列表的介绍见:
http://iyenn.com/rec/1709317.html

昊虹嵌入式技术交流群
QQ群名片
注:本文转载自blog.csdn.net的昊虹AI笔记的文章"https://blog.csdn.net/wenhao_ir/article/details/145422877"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top