C++指针与引用详解
在 C++ 编程中,指针和引用是两种常见的变量间接访问方式。它们虽然有相似之处,但在用法和概念上有很大区别。本篇笔记将详细解释指针和引用的概念、用法以及它们的区别。
1. 引用的基本概念
引用是为变量创建一个别名。它允许你通过另一个名字来操作变量,但不会为变量开辟新的内存空间。引用在定义时必须初始化,并且一旦初始化后不能再指向其他变量。
int max = 20;
int &refmax = max; // refmax 是 max 的引用
refmax = 5; // max 变为 5
特点:
引用必须初始化
不能声明一个没有初始化的引用。例如,以下代码会报错:int &refmax; // 错误,没有初始化
正确的做法是:
int max = 20; int &refmax = max; // 正确
引用不能指向常量
不能将常量值直接作为引用变量的初始化值,例如:int &ref = 5; // 错误,5 不是一个有效的变量
引用与原变量共享内存地址
引用本身并没有新的内存空间,而是与原变量共享同一内存地址,因此改变引用的值实际上是修改了原变量的值。引用可以作为指针的目标
引用有地址,你可以用指针来引用它:int a = 10; int &ref = a; int *p = &ref; // p 指向 ref 的地址 *p = 20; // a 变为 20
2. 引用的常见用法
1)引用作为函数参数
引用常用作函数的参数,可以避免复制的开销,并且能直接修改传入的实参。
void change(int &x, int &y) {x = x + y;y = x - y;x = x - y;
}int main() {int a = 3, b = 5;change(a, b); // a 和 b 的值被修改std::cout << a << " " << b << std::endl;
}
2)引用作为函数返回值
返回引用类型的函数允许直接对返回值进行赋值操作。注意,返回的引用必须指向有效的内存地址,例如全局变量或静态局部变量。返回局部变量的引用会导致未定义行为。
int& getData() {static int x = 10; // 使用静态变量return x;
}int main() {getData() = 20; // 直接赋值给 getData 返回的引用std::cout << getData() << std::endl; // 输出 20
}
3. 引用与指针的区别
指针通过地址访问变量,而引用直接访问变量
指针需要通过地址间接访问变量,而引用本质上是变量的别名,可以直接访问该变量。指针可以重新指向其他变量,而引用一旦绑定则不能改变
指针可以重新指向其他地址,而引用在初始化后就不能改变指向。引用必须在声明时初始化
与指针不同,引用一旦声明就必须进行初始化,且之后不能再指向其他变量。
int x = 5;
int y = 10;
int* p = &x; // 指针可以改变指向
p = &y; // 指向 yint& ref = x; // 引用必须在声明时初始化,且之后不能更改
// ref = y; // 错误,ref 永远指向 x
4. 常量引用
常量引用是引用的一种特殊形式,声明时使用 const
修饰,表示该引用指向的变量不允许被修改。
const int &r = 10; // 常量引用
// r = 20; // 错误,不能修改常量引用的值
std::cout << r << std::endl; // 输出 10
常量引用常用于避免拷贝大型对象,同时保证对象不被修改。
你说得对,这部分确实涉及到了 常指针(const pointer)和 指针常量(pointer to const),下面我会在原来的基础上加以补充说明:
5. 禁止写入的指针
1) 禁止指针本身修改:常指针
常指针(const
修饰指针本身)指的是指针本身的值(即存储的地址)不可修改,但指针指向的内容仍然可以修改。
int x = 10;
int* const ptr = &x; // ptr 是一个常指针,指向 x
*ptr = 20; // 允许修改 ptr 指向的内容
常指针 使得指针变量
ptr
一旦初始化后就不能再指向其他地址,指针的值是固定的,但它所指向的内容仍然可以修改。
2) 禁止间接修改指针指向的内容:指向常量的指针
指向常量的指针(const
修饰指针指向的内容)指的是指针指向的内容不能被修改,但指针本身可以改变指向。
const int* ptr = &x; // ptr 是一个指向常量的指针
*ptr = 20; // 错误,不能修改 *ptr(指针指向的内容)
ptr = &y; // 允许修改 ptr 的指向
指向常量的指针 表示指针所指向的数据是不可修改的,但可以指向其他的地址。这里通过
const
修饰的是指针所指向的数据,而非指针本身。
3) 禁止指针本身和间接修改:常指针常量
常指针常量(const
修饰指针本身和指针指向的内容)指的是既不能修改指针本身的值(即无法改变指针指向的地址),也不能修改指针指向的内容。
const int* const ptr = &x; // ptr 是一个常指针常量
*ptr = 20; // 错误,无法修改 *ptr
ptr = &y; // 错误,无法修改 ptr 的指向
常指针常量 限制了指针本身和指针所指向的内容都不可修改。一旦指针被初始化,它所指向的地址和数据都被锁定,不可以改变。
- 常指针(
int* const ptr
)指针本身不可修改,但可以修改它指向的内容。 指向常量的指针(
const int* ptr
)指针本身可以修改,但不能修改它指向的内容。常指针常量(
const int* const ptr
)既不能修改指针本身,也不能修改它指向的内容。
总结
指针和引用是 C++ 中两个重要的概念,它们在内存管理、函数参数传递和性能优化方面都有着广泛的应用。理解它们的区别和用法是深入掌握 C++ 编程的关键。