首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >【C/C++】C++引用和指针的对比

【C/C++】C++引用和指针的对比

作者头像
艾莉丝努力练剑
发布于 2025-11-12 19:09:50
发布于 2025-11-12 19:09:50
3820
举报
文章被收录于专栏:C / C++C / C++

前言:本专栏记录了博主C++从初阶到高阶完整的学习历程,会发布一些博主学习的感悟、碰到的问题、重要的知识点,和大家一起探索C++这门程序语言的奥秘。这个专栏将记录博主C++语法、高阶数据结构、STL的学习过程,正所谓“万丈高楼平地起”嘛,我们话不多说,继续进行C++阶段的学习。本文我们不讲C++主线的内容,我们来拓展一下或者说整理一下我们学习时C/C++时经常会提到的一些专有名词,例如形参、实参,显式类型转换和隐式类型转换类型转换,内置类型等等。

C++的两个参考文档:

老朋友(非官方文档):cplusplus 官方文档(同步更新):cppreference

正文

博主之前写过C++引用相关的内容,只不过那是在C++初识部分介绍的,比较简略:

【C/C++】初识C++(二):深入详解缺省参数(默认参数)函数重载、引用(重头戏)

【C/C++】初识C++(三):C++入门内容收尾——const引用,指针和引用关系梳理,inline(内联函数),nullptr替代NULL

引用是C++中一种重要的特性,它提供了对变量的别名机制,使得我们可以用不同的名称访问同一块内存空间。下面全面介绍C++引用的核心知识点。

一、引用的基本概念

1、定义与声明
代码语言:javascript
复制
int num = 10;
int &ref = num;  // ref是num的引用
  • 引用必须在声明时初始化
  • 引用一旦绑定到一个变量,就不能再绑定到其他变量
  • 引用不是对象,不占用额外存储空间(编译器实现可能不同)
2、引用与指针的区别

特性

引用

指针

初始化要求

必须初始化

可以不初始化

可修改性

不能重新绑定

可以指向不同对象

空值

不能为空

可以为NULL/nullptr

操作方式

直接使用

需要解引用(*)

内存占用

通常不占额外空间

占用指针大小的空间

二、引用的主要用途

1、函数参数传递
代码语言:javascript
复制
void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}
  • 避免拷贝大对象的开销
  • 允许函数修改实参的值
  • 比指针更安全(不能为null)
2、函数返回值
代码语言:javascript
复制
int &getMax(int &a, int &b) {
    return a > b ? a : b;
}

int main() {
    int x = 5, y = 10;
    getMax(x, y) = 20;  // 修改了y的值
}
  • 可以返回引用实现左值调用
  • 不能返回局部变量的引用(会导致悬空引用)

三、const引用

1、常量引用
代码语言:javascript
复制
const int &ref = 42;  // 合法:常量引用可以绑定到字面量
2、函数参数中的const引用
代码语言:javascript
复制
void print(const std::string &str) {
    // 不能通过str修改原对象
    std::cout << str;
}
  • 避免不必要的拷贝
  • 保证函数内不会修改参数
  • 可以接受临时对象和字面量

四、引用与右值引用(C++11)

1、左值引用 vs 右值引用
代码语言:javascript
复制
int a = 10;
int &lref = a;       // 左值引用
int &&rref = 20;     // 右值引用
2、移动语义
代码语言:javascript
复制
class MyString {
public:
    // 移动构造函数
    MyString(MyString &&other) noexcept {
        data = other.data;
        other.data = nullptr;
    }
};

五、引用折叠规则(C++11)

代码语言:javascript
复制
template<typename T>
void func(T&& param) {  // 万能引用
    // 根据传入参数决定引用类型
}

int a = 10;
func(a);   // T&
func(10);  // T&&

六、特殊引用情况

1、引用数组
代码语言:javascript
复制
int arr[5] = {1, 2, 3, 4, 5};
int (&refArr)[5] = arr;  // 数组的引用
2、指向指针的引用
代码语言:javascript
复制
int *ptr = nullptr;
int *&refPtr = ptr;  // 指向指针的引用

七、引用使用的最佳实践

  1. 函数参数优先使用const引用传递大对象
  2. 需要修改参数时使用普通引用
  3. 避免返回局部变量的引用
  4. 明确区分左值引用和右值引用
  5. 谨慎使用引用作为类成员(可能引入生命周期问题)

八、常见错误

1、 返回局部变量引用
代码语言:javascript
复制
int &badFunc() {
    int local = 10;
    return local;  // 错误!
}
2、未初始化的引用
代码语言:javascript
复制
int &ref;  // 错误:必须初始化
3、引用NULL
代码语言:javascript
复制
int &ref = NULL;  // 错误

引用是C++强大而独特的特性,正确使用引用可以写出更高效、更安全的代码,但同时需要注意其特性和限制以避免潜在问题。

九、详解C++引用

引用基础
1、基本引用示例
代码语言:javascript
复制
#include <iostream>
using namespace std;

int main() {
    int original = 42;
    int &ref = original;  // 引用声明和初始化
    
    cout << "original: " << original << endl;  // 42
    cout << "ref: " << ref << endl;            // 42
    
    ref = 100;  // 通过引用修改值
    
    cout << "after change:" << endl;
    cout << "original: " << original << endl;  // 100
    cout << "ref: " << ref << endl;            // 100
    
    // 验证它们共享同一地址
    cout << "Address of original: " << &original << endl;
    cout << "Address of ref: " << &ref << endl;  // 相同地址
}
2、引用与指针对比
代码语言:javascript
复制
void compareRefAndPointer() {
    int x = 10;
    
    // 引用方式
    int &ref = x;
    ref = 20;  // 直接使用
    
    // 指针方式
    int *ptr = &x;
    *ptr = 30;  // 需要解引用
    
    cout << "x after ref change: " << x << endl;
    cout << "x after ptr change: " << x << endl;
    
    // 尝试重新绑定
    int y = 50;
    // ref = y;  // 错误!不能重新绑定引用
    ptr = &y;    // 指针可以重新指向
}
(二)函数中的引用
1、引用参数示例
代码语言:javascript
复制
// 交换两个变量的值
void swap(int &a, int &b) {
    int temp = a;
    a = b;
    b = temp;
}

void testSwap() {
    int x = 10, y = 20;
    cout << "Before swap: x=" << x << ", y=" << y << endl;
    swap(x, y);
    cout << "After swap: x=" << x << ", y=" << y << endl;
}
2、返回引用示例
代码语言:javascript
复制
// 返回数组元素的引用
int &getElement(int arr[], int index) {
    return arr[index];
}

void testReturnRef() {
    int numbers[] = {10, 20, 30, 40, 50};
    
    // 获取引用并修改
    getElement(numbers, 2) = 100;
    
    cout << "Modified array: ";
    for (int num : numbers) {
        cout << num << " ";
    }
    cout << endl;
    
    // 错误示例:返回局部变量引用
    /*
    int &badRef() {
        int local = 42;
        return local;  // 警告:返回局部变量引用
    }
    */
}
(三)const引用
1、const引用基础
代码语言:javascript
复制
void constRefDemo() {
    int a = 10;
    const int &ref1 = a;  // 合法
    // ref1 = 20;        // 错误:不能通过const引用修改
    
    const int b = 20;
    const int &ref2 = b;  // 合法
    
    // 绑定到临时对象
    const int &ref3 = 30;  // 合法
    cout << "ref3: " << ref3 << endl;
}
2、const引用参数
代码语言:javascript
复制
void printLargeObject(const string &str) {
    cout << str << endl;
    // str[0] = 'A';  // 错误:不能修改
}

void testConstRefParam() {
    string longStr(1000, 'x');  // 大字符串
    printLargeObject(longStr);   // 避免拷贝
    
    // 可以接受临时对象
    printLargeObject("Temporary string");
}
(四)右值引用(C++11)
1、基本右值引用
代码语言:javascript
复制
void rvalueRefDemo() {
    int &&rref1 = 10;  // 右值引用
    
    int x = 10;
    // int &&rref2 = x;  // 错误:不能绑定左值
    
    rref1 = 20;  // 可以修改
    cout << "rref1: " << rref1 << endl;
}
2、移动语义示例
代码语言:javascript
复制
class StringWrapper {
    char *data;
public:
    // 构造函数
    explicit StringWrapper(const char *str = "") {
        data = new char[strlen(str) + 1];
        strcpy(data, str);
    }
    
    // 移动构造函数
    StringWrapper(StringWrapper &&other) noexcept {
        data = other.data;
        other.data = nullptr;
    }
    
    // 移动赋值运算符
    StringWrapper &operator=(StringWrapper &&other) noexcept {
        if (this != &other) {
            delete[] data;
            data = other.data;
            other.data = nullptr;
        }
        return *this;
    }
    
    ~StringWrapper() {
        delete[] data;
    }
    
    void print() const {
        cout << (data ? data : "null") << endl;
    }
};

void testMoveSemantics() {
    StringWrapper sw1("Hello");
    StringWrapper sw2 = std::move(sw1);  // 使用移动构造函数
    
    cout << "After move:" << endl;
    cout << "sw1: ";
    sw1.print();  // 输出 null
    cout << "sw2: ";
    sw2.print();  // 输出 Hello
}
(五)高级引用用法
1、引用数组
代码语言:javascript
复制
void refArrayDemo() {
    int arr[3] = {1, 2, 3};
    int (&refArr)[3] = arr;  // 数组的引用
    
    refArr[1] = 20;  // 修改原数组
    
    cout << "Original array: ";
    for (int n : arr) {
        cout << n << " ";
    }
    cout << endl;
}
2、指向指针的引用
代码语言:javascript
复制
void pointerRefDemo() {
    int x = 10;
    int *ptr = &x;
    int *&refPtr = ptr;  // 指向指针的引用
    
    *refPtr = 20;  // 修改x的值
    cout << "x: " << x << endl;
    
    int y = 30;
    refPtr = &y;    // 修改指针指向
    *refPtr = 40;
    cout << "y: " << y << endl;
}
(六)综合应用示例
1、链式调用
代码语言:javascript
复制
class Counter {
    int count;
public:
    Counter() : count(0) {}
    
    Counter &increment() {
        ++count;
        return *this;
    }
    
    Counter &decrement() {
        --count;
        return *this;
    }
    
    int get() const { return count; }
};

void testChaining() {
    Counter c;
    c.increment().increment().decrement();
    cout << "Count: " << c.get() << endl;  // 输出 1
}
2、引用作为类成员
代码语言:javascript
复制
class Logger {
    ostream &out;
public:
    explicit Logger(ostream &os = cout) : out(os) {}
    
    void log(const string &msg) {
        out << msg << endl;
    }
};

void testLogger() {
    Logger consoleLogger;
    consoleLogger.log("This goes to console");
    
    ofstream file("log.txt");
    Logger fileLogger(file);
    fileLogger.log("This goes to file");
}

博主展示的这些代码示例,涵盖了C++引用的各种用法,从基础到高级特性。通过实际运行这些代码,可以更深入地理解引用的工作原理和应用场景。


结尾

往期回顾:

【C/C++】形参、实参相关内容整理

【C/C++】Dev-C++的安装与使用以及快捷键整理

【日常问题解决方案】VS2022不小心解决方案资源管理器把关掉了怎么办

VS2022进行监视功能的步骤

结语:本文内容到这里就全部结束了。本文我们重新整理了C++引用和指针相关的内容。

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-08-07,如有侵权请联系 cloudcommunity@tencent.com 删除
目录
  • 正文
    • 一、引用的基本概念
      • 1、定义与声明
      • 2、引用与指针的区别
    • 二、引用的主要用途
      • 1、函数参数传递
      • 2、函数返回值
    • 三、const引用
      • 1、常量引用
      • 2、函数参数中的const引用
    • 四、引用与右值引用(C++11)
      • 1、左值引用 vs 右值引用
      • 2、移动语义
    • 五、引用折叠规则(C++11)
    • 六、特殊引用情况
    • 七、引用使用的最佳实践
    • 八、常见错误
      • 1、 返回局部变量引用
      • 2、未初始化的引用
      • 3、引用NULL
  • 九、详解C++引用
    • 引用基础
    • (二)函数中的引用
    • (三)const引用
    • (四)右值引用(C++11)
    • (五)高级引用用法
    • (六)综合应用示例
  • 结尾
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档