文章目录
C++中指针和引用的区别
一、定义和声明的方式
指针
定义:指针是一个变量,其值为另一个变量的地址,指针本身也占用内存空间。
声明:使用*符号进行声明
int a = 10;
int* p = &a; // 定义指针并初始化
引用
定义:引用是某个变量的别名,一旦引用被绑定到一个对象,就不能再指向其他对象。不占用存储空间。
声明:引用使用&符号进行声明
int a = 10;
int& ref = a; // 定义引用并绑定
二、是否可为空值
指针可以为 nullptr 或 NULL,表示不指向任何对象。但是引用必须绑定到有效对象,不能为空。
三、语法与操作
指针
指针使用 * 声明和解引用(如 int *p = &a; *p = 10;)。
当指针指向的对象为类时,可使用 -> 访问成员(如 p->member)。
引用
使用 & 声明,但无需显式解引用(如 int &r = a; r = 10;)。
当指针指向的对象为类时,可直接使用 . 访问成员(如 r.member)。
四、常量性
指针
1.指向常量的指针(const T*)
p 是一个指针,指向一个不可变的int常量。
可以改变指针p指向的地址,但不能通过p修改它指向的值。
const int a = 10;
const int* p1 = &a; // 指向常量对象a
// *p1 = 40; // ❌ 错误:不能通过 p1 修改 c
a = 40; // ✅ 合法:直接修改原对象
int b = 20;
p1 = &b; // 指向非 const 对象(但无法通过 p1 修改 b)
2.常量指针(T* const)
p 是一个常量指针,始终指向初始化时的地址。
即不能改变指针p的地址,但可以通过p修改它指向的值。
int c = 60;
int* const p2 = &c; // ✅ 合法:指针地址不可变
*p2 = 70; // ✅ 合法:修改指向的对象
int d = 20;
// p2 = &d; // ❌ 错误:指针本身不可修改
3.指向常量的常量指针(const T* const)
p 是一个常量指针,既不能改变指针指向的地址,也不能修改它指向的值。
完全不可变,起到只读访问的作用。
const int e = 90;
const int* const p6 = &e; // ✅ 合法
// *p3 = 100; // ❌ 错误:不能通过 p3 修改 f
// p3 = &a; // ❌ 错误:不能改变指向
引用
通过引用无法修改原对象。
const int &r = 5;
// 等价于:
const int _temp = 5; // 编译器生成临时变量
const int &r = _temp; // 引用绑定到临时变量
//int &r1 = 5; // ❌ 错误:非 const 引用不能绑定到右值
//r = 20; // ❌ 错误:通过引用无法修改原对象的值
五、常见应用场景
指针
1.动态内存分配:
指针用于分配和释放动态内存,尤其在需要动态确定数组大小或对象数量时。
int* p = new int[10]; // 动态分配内存
delete[] p; // 释放内存
2.数据结构实现:
用于实现链表、二叉树等需要动态链接节点的数据结构。
struct Node {
int data;
Node* next; // 指向下一个节点
};
引用
1.函数参数传递:
引用用于将变量作为参数进行传递,可防止传参时溢出,如果不希望更改变量的值,可以加上const。
void printValue(const int& value) {//常量引用保护值不被修改。
std::cout << value;
}
2.函数返回值:
函数可以通过引用返回一个变量,使调用者直接操作返回值。
int& getValue(int& x) {
return x; // 返回引用
}
总结
用指针:需动态内存管理、可选绑定、或实现复杂数据结构(如链表)。
用引用:需简化语法、避免拷贝、或强制绑定有效性(如函数参数传递)。
int x = 10;
int* ptr = &x;//指针指向x的地址
cout <<"x原始的值" << x << endl;
*ptr = 11;//修改指针指向的值
cout << "修改后x的值" << x << endl << endl;
ptr = nullptr;//指针可以指向空地址
//cout << *ptr << endl;//空地址不能访问
int y = 20;
int& ref = y;//引用指向y,引用是一个变量的别名
cout << "y原始的值" << y << endl;
ref = 21;//修改引用的值
cout << "修改后y的值" << y << endl;
//ref = nullptr;不能这样使用引用,引用不可以指向空地址,引用必须初始化,没有空引用这个概念
ptr = &y;//指针可以改变指向
cout << "指针改变指向后,原来变量的值不变" << x << endl;
ref = x;//这并不是改变 ref 的绑定,而是将 x 的值赋给 y,修改的是 y 的值
cout << "修改后y的值" << y << endl;
const int* p1 = &x;//指向常量的指针,指针指向的值不能改变,指针指向的地址可以改变
// *p1 = 12;不能修改指针指向的值
p1 = &y;//可以修改指针指向的地址
const int& r1 = x;//指向常量的引用,引用指向的值不能改变,引用指向的地址不能改变
//r1 = 13;不能修改引用指向的值