1、非 const 的引用必须指向一个已存在的变量
int main() {
int &a = 20; // 错误
const int &b = 30;
}
- 字面量
20是临时值(右值),没有明确的内存地址。 - 非常量引用(左值引用)不能直接绑定到右值(如字面量)。
- 常量引用可以绑定到右值。编译器会为字面量
30生成一个临时变量,并将b作为该临时变量的别名。此时临时变量的生命周期会被延长至引用b的作用域结束。
2、在内存的 0x0018ff44 处写一个4字节的10
*reinterpret_cast<int*>(0x0018ff44) = 10;
3、指针与 const 的结合
int main() {
int a = 10;
const int* p1 = &a;
int* const p2 = &a;
const int* const p3 = &a;
// 哪些赋值是合法的?
*p1 = 20; // ①
p1 = &a; // ②
*p2 = 20; // ③
p2 = &a; // ④
*p3 = 20; // ⑤
p3 = &a; // ⑥
return 0;
}
- 合法:②、③
- 非法:①(
p1指向const int)、④(p2是常量指针)、⑤(p3指向const int)、⑥(p3是常量指针)。
4、引用与 const 的结合
int main() {
int a = 10;
const int& r1 = a;
int& const r2 = a; // 编译错误
// 哪些赋值是合法的?
a = 20; // ①
r1 = 20; // ②
return 0;
}
int& const r2 这种写法是冗余且错误的。 若想让引用不能修改所绑定的对象,应使用 const int& r2 = a;(常量引用)
引用本身具有 “一旦绑定某个对象,就不能再绑定其他对象” 的特性
①合法
②不合法。r1 是 const int&(常量引用),它承诺不通过自身修改所绑定的对象(即不能通过 r1 改变 a 的值)。因此,r1 = 20; 试图通过常量引用修改值,是非法操作,会导致编译错误。
5、指针、引用与临时对象
int& getRef() {
int temp = 10;
return temp; // 危险?
}
const int& createRef() {
return 10; // 合法?
}
int* getPtr() {
int arr[3] = {1, 2, 3};
return arr; // 危险?
}
6、const int*& func(int*& p);
func 是一个函数,接受 int*&(指针的引用),返回 const int*&(指向常量 int 的指针的引用)。
int x = 10;
int* ptr = &x;
const int*& ref = func(ptr); // ref 是一个指向 const int* 的引用
7、const 对象,不能调用非 const 方法
class MyClass {
public:
void nonConstFunc() { /* 可能修改对象状态 */ }
void constFunc() const { /* 承诺不修改对象状态 */ }
};
int main() {
const MyClass obj;
obj.nonConstFunc(); // 编译错误,const 对象不能调用非 const 方法
obj.constFunc(); // 合法,调用 const 成员方法
return 0;
}
8、解释以下声明的含义并指出区别
const int* p1;
int* const p2;
const int* const p3;
区分「指针指向的内容不可变」与「指针本身不可变」
const int* p1:指向常量的指针,指针可重定向,但内容不可通过p1修改(保护数据)int* const p2:常量指针,指针不可重定向,但内容可通过p2修改(保护指针)const int* const p3:指针和内容均不可变(双重保护)
在 C++ 中,const 修饰离它最近的类型
核心是理解:到底在保护谁?保护其不变化
| 序号 | 声明 | const修饰的部分 | 指针性质 | 能否通过指针修改所指内容 |
|---|---|---|---|---|
| 1 | const int *p; | int |
普通指针(指针可变) 保护的是对应地址上的值不变 | 否 |
| 2 | int const* p; |
与 | 普通指针(指针可变,没修饰*p) | 否 |
| 3 | int *const p; | p(指针本身) | 常量指针(指针不可变;内容可变,没修饰*p) | 是 |
| 4 | const int *const p; | int和p(指针本身) | 常量指针(指针不可变) | 否 |
int *const p;:const修饰p,p是一个常量指针(指针本身不可变,不能再指向其他地址),但它指向普通int,可以通过p修改所指内容。
int a = 10;
int b = 20;
int *const p3 = &a; // 注释 int <= int
int *p4 = p3; // 注释 int <= int*p3 指向 a的地址,这个不可变,保护的是“p3的值就是a的地址”这个绑定。
p4的类型是int*(普通指针),并不会改变这种保护关系。*p4 = 10; 或者p4 = &b;都不会影响“p3的值就是a的地址”。
9、指针与引用声明的类型匹配规则
int a = 10;
int *p = &a;
int *&q = p;
int *&q = p; 中 q 是指针 p 的引用,类型完全匹配,声明合法。
int a = 10;
int *const p = &a;
int *&q = p;
int *const p = &a; 中 p 是常量指针(指针本身不可变),类型为 int *const;而 int *&q = p; 中 q 是 int *&,int *const 与 int *& 类型不匹配(常量性不同),声明非法。
int a = 10;
const int *p = &a;
int *&q = p;
const int *p = &a; 中 p 是指向 const int 的指针,类型为 const int *;int *&q = p; 中 q 是 int *&,const int * 与 int *& 类型不匹配(底层 const 存在差异),声明非法
int a = 10;
int *p = &a;
const int *&q = p;
int *p = &a; 中 p 是普通指针(int *);const int *&q = p; 中 q 是 const int *&,int * 与 const int *& 类型不匹配(底层 const 存在差异),声明非法。
10、普通指针指向常量——错误
const int a = 10;
int *p = &a; // 错误:普通指针不能指向常量对象
普通指针不能指向常量(否则可能通过指针修改常量,破坏常量的 “只读” 特性),应使用 const int *p = &a;(const int * 类型指针指向 const int 对象)。所以原代码编译不通过
const常量:初始化后值不可改变,不能作为左值重新赋值。const常量:可能在编译期直接将值放入符号表,供编译器优化使用(类似宏常量,但有类型安全检查)。- 普通变量:运行时分配内存,值存于内存中,每次访问从内存读取。
const常量:通常存储在只读数据段(某些优化场景下可能不分配实际内存,直接用符号表值替代)。- 普通变量:存储在栈(局部变量)或全局数据区(全局 / 静态变量),有实际内存空间。
const int arr_size = 5;
int arr[arr_size]; // C++ 中合法,const 常量可用于数组长度(编译期确定)
int non_const_size = 5;
// int arr2[non_const_size]; // C++ 中非法,普通变量值运行时确定,不能用于数组长度
在 C++ 中,“不能把常量的地址泄露给一个普通的指针或者普通的引用变量”
11、const与二级指针
int main()
{
int a = 10;
int *p = &a;
const int **q = &p;
return 0;
}
p是int*类型(指向int的指针)。&p是int**类型(指向int*的指针)。q是const int**类型(指向const int*的指针)。
禁止将 int** 直接赋值给 const int**
int**表示指向int*的指针 。int*是“指向非常量整数的指针”。const int**表示指向const int*的指针。const int*是“指向常量整数的指针”int**和const int**是两种不同的类型,无法隐式转换
int main() {
int a = 10;
int *p = &a;
const int **q = &p; // 假设允许赋值(实际报错)
const int c = 20;
*q = &c; // 让 *q(即 p)指向 const int c
*p = 30; // 通过 p 修改 c 的值(危险!)
return 0;
}
12、综合题
A: const int *p 表示 p 指向 const int,不能将 const int * 类型的指针赋值给 int * 类型的 q,因为这会破坏 const 限定,允许通过 q 修改 p 指向的值,错误。
int a = 10;
const int *p = &a;
int *q = p;
B:int *const p 表示 p 是常量指针(指针本身的值不能改变),但类型是 int *,可以将 int * 类型的 p 赋值给 int * 类型的 q,正确
int a = 10;
int *const p = &a;
int *q = p;
C:int *const p 是常量指针,int *const q = p; 表示 q 也是常量指针,将 int *const 类型的 p 赋值给 int *const 类型的 q,正确
int a = 10;
int *const p = &a;
int *const q = p;
D:int *const p 是 int * 类型的常量指针,const int *q = p; 表示 q 是指向 const int 的指针,int * 类型可隐式转换为 const int * 类型,正确
int a = 10;
int *const p = &a;
const int *q = p;
E: int *const *q = &p; 表示 q 是一个指针,指向 int *const(即指向一个常量指针,该指针本身不可变)。此处赋值仅约束通过 q 访问时 *q 为常量指针,不影响原始 p 的定义,因此类型匹配,代码合法。
int a = 10;
int *p = &a;
int *const *q = &p;
F:错误。const int** 不能隐式转换为 int *const*
int a = 10; // 定义整型变量a并初始化为10
const int *p = &a; // 定义指向常量整型的指针p,指向a的地址
int *const * q = &p; // 定义指向"指向整型的常量指针"的指针q,指向p的地址
p是指向const int的指针(常量指针)
- 等价于
int const *p - 特性:可以通过p读取a的值,但不能通过p修改a的值,
p本身可再指向其他地址
q是指向「指向int的常量指针」的二级指针
&p实际类型为const int**, p的类型是const int*q声明类型为int* const*
2028

被折叠的 条评论
为什么被折叠?



