指针和const
1.普通指针
- 指针本身指向可以修改,其指向的变量本身可以自行修改,或者是通过指针解引用修改
// 变量统一采用括号初始化
int x { 5 };
int* ptr { &x };
// 修改
// 1.改变指向
int y { 6 };
ptr = &y;
// 2.通过指针解引用修改变量
*ptr = 7;
2.指向常量的指针
- 指针本身的指向可以修改,但是其指向的变量被指针视为常量,不可以通过指针解引用修改
- 但是指向的变量可以是真正的常量抑或非常量,非常量时可以通过自身进行修改
// 1.指向非常量的常量int类型指针
int x{ 5 };
const int* ptr { &x };
*ptr = 6; // 不允许
x = 6; // 允许
// 2.指向常量的常量int类型指针
const int x{ 5 };
const int* ptr { &x };
*ptr = 6; // 不允许
x = 6; // 不允许
3.常量指针
- 指针本身作为常量,其指向自然不可以修改,但是其指向的变量不受影响
int x{ 5 };
int y{ 6 };
int* const ptr { &x };
ptr = &y; // 不允许
x = 7; // 允许
4.指向常量的常量指针
- 指针本身作为常量的同时,其指向也看作常量,指向不能修改,指向的变量也不可以通过指针解引用的形式修改
- 但是指向的值可以时一个非常量,此时可以通过对变量自身操作,进行修改
int value { 5 };
int y{ 6 };
const int* const ptr { &value };
ptr = &y; // 不允许
value = 66; // 允许
*ptr = 6; // 不允许
为了方便记忆擅自做出以下约定:
- 统一从左往右读
- const int* ptr { &x }; int常量类型的指针----- 指向常量
- int* const ptr { &x }; int类型的常量指针----- 指针常量
- const int* const ptr { &value }; int常量类型的常量指针----- 常量的常量指针
引用
- 使用左值引用时必须被初始化
- 左值引用必须被绑定到一个可修改左值
- 引用一旦被初始化,它便不能够被重新绑定到其他对象,针对引用来进行的,修改引用对象的行为,会反映到其引用的变量上而不是引用自身
int x { 5 };
int y { 6 };
int& ref { x };
ref = y; // 并不会修改ref,而是相当于修改 x=y
std::cout << x; // 输出6
- 被引用对象可以先于引用销毁,引用可以先于被引用对象销毁。
- 当一个对象先于它的引用被销毁,则其引用此时会绑定到一个已经不存在的对象。此时该引用会成为一个悬垂引用。访问悬垂引用会导致未定义行为
引用与const
- 指向 const 的左值引用
- 即,要求左值引用将其引用的对象当做const看到,此时就可以引用一个const值
// 1.const左值引用绑定不可修改的左值
const int x { 5 };
const int& ref { x }; // 此时是允许的
int& ref2 { x }; // 不允许
ref = 6; // 不允许
// 可以用于访问但不能修改被引用的值
// 2. const左值引用也可以绑定到可修改的左值
- 使用右值初始化const左值引用
const int& ref { 5 };
- 当const左值引用被绑定到一个临时对象时,临时对象的生存期将被扩展到与引用的生存期相匹配。
const int& ref { 5 }; // 正常来说5在}结束后销毁,那么之后ref会引用一个已经被销毁的对象,ref变成悬垂引用,当我们试图访问 ref 时,将产生未定义行为。
// 为了避免这种情况下的悬垂引用,C++有一个特殊的规则:当const左值引用被绑定到一个临时对象时,临时对象的生存期将被扩展到与引用的生存期相匹配。
const int& ref { 5 };
std::cout << ref; // 在这种规则下,5依旧可存活,直到ref被销毁
指针与const与引用的应用案例
void query_balance(const string* name, const int* const balance) { // balance指向的变量和它本身不可以改
cout << "---查询余额---\n";
cout << *name << ",您好,您的余额:" << *balance << "元\n";
}
// 存款
void deposit_balance(const string* name, int* const balance, const int& cash) { // balance本身不可以更改指向,但是其解引用的变量可以计算修改
cout << "---存款---\n";
cout << *name << ",您好,您存款" << cash << "元成功!\n";
*balance += cash; // 体现对*balance的修改
cout << *name << ",余额:" << *balance << endl;
}