const限定符

c++中,const(常量限定符)的核心作用时 声明“不可修改”的实体 ,前置编译器保证“只读性”。可以修饰变量、指针、引用、成员函数、函数参数/返回值等。

一、核心思想

const的本质是“编译期间检查的制度契约”:

  • const修饰的实体, 编译阶段不允许通过该实体修改其值 (运行时仍然可能通过其他非const途径修改,除非是编译时常量);
  • 违反契约会直接编译报错而非运行时错误,提前规避bug

二、const的常见用法

1.修饰普通变量(常量)

最基础的用法:声明“不可修改的变量”, 必须初始化(否则编译报错)。

const int max_size = 100; // 正确:编译期常量,不可修改 
max_size = 200; // 错误:const 变量不能被赋值 
// 注意:const 变量的作用域与普通变量一致,全局 const 默认内部链接(需 extern 显式声明外部链接)

#define的区别(关键)
const变量是类安全的,而#define是文本替换(无类型、无作用域):

const int a = 3; #define B 3 
int x = a + 1;  // 编译时已知 a=3,可优化 
int y = B + 1;  // 预处理替换为 3+1,无类型检查 
// 若 #define B "3",则 y = "3"+1 会编译报错,但 #define 本身不做类型校验

2.修饰指针

(1)指向常量的指针(const T* p

const修饰指针指向的内容:内容不可改,指针本身可改(可指向其他地址)。

int a = 10, b = 20; 
const int* p = &a; // p 指向 a,a 的值不能通过 p 修改 
*p = 30; // 错误:不能通过 p 修改指向的内容 
p = &b; // 正确:指针 p 可指向其他地址
(2)常量指针(T* const p

const修饰指针变量本身:指针不可变(不能指向其他地址),指向的内容可修改。

int a = 10, b = 20;
 int* const p = &a; // p 是常量指针,必须初始化(指向 a) 
 p = &b; // 错误:指针 p 不能指向其他地址 
 *p = 30; // 正确:可通过 p 修改 a 的值(a 本身非 const)
(3)指向常量的常量指针(const T* const p

const同时修饰”内容“和”指针“:两者都不可以修改。

const int* const p = &a; 
*p = 30; // 错误:内容不可改 
p = &b; // 错误:指针不可改

记忆技巧
const靠近谁,谁就不可以修改:

  • const T* p - const靠近T(内容) - 内容不可以修改;
  • T* const p - const靠近p(指针) - 指针不可以修改。

3.修饰引用(常量引用const T&)

const修饰引用时,声明‘不能通过该引用修改被引用的对象’,核心用途:

  • 避免拷贝(传递大对象时高效,如std::string、自定义类);
  • 保护实参(防止函数内部意外修改实参)
void print(const std::string& s) { 
	// s += "test"; // 错误:const 引用不能修改被引用对象 
	std::cout << s << std::endl; 
} 
int main() { 
	std::string str = "hello"; print(str); // 实参 str 不会被修改,且无拷贝开销 
	
	// 常量引用还能绑定临时对象(普通引用不能) 
	print("world"); // 正确:临时字符串 "world" 绑定到 const 引用 
	return 0; 
}

4.修饰类的成员函数(double number_value() const;

最常用的场景之一:声明常成员函数,核心规则:

  • 常成员函数不能修改类的非静态数据成员
  • 常成员函数不能调用类的非const成员函数(只能调用const成员函数);
  • 成员函数的this指针式const T*类型(普通成员函数的thisT*),因此无法通过this修改成员变量。
    示例解析
class Number { 
private: 
	double value = 3.14; // 非静态数据成员 
public: 
	// 常成员函数:承诺不修改对象状态 
	double number_value() const { 
		// value = 5.20; // 错误:不能修改非静态成员变量 
		return value; // 正确:只读访问成员变量 
	} 
	
	void set_value(double v) { // 非 const 成员函数:可修改对象 
		value = v; 
	} 
};

关键用法:常对象只能调用常成员函数

  • 普通对象(Numbew obj):可到用 const 和非 const 成员函数;
  • 常对象(const Number obj):只能调用 const 成员函数(因为对象本身不可修改,非 const 成员函数可能修改对象)。
int main() { 
	Number obj1; // 普通对象 
	obj1.number_value(); // 正确(调用 const 成员函数) 
	obj1.set_value(2.71); // 正确(调用非 const 成员函数) 
	
	const Number obj2; // 常对象 
	obj2.number_value(); // 正确(常对象只能调用 const 成员函数) 
	// obj2.set_value(1.68); // 错误:常对象不能调用非 const 成员函数 
	return 0; 
}

例外:mutable修饰的成员变量
若成员变量被 mutable 修饰,则即使在常成员函数中,也可修改该变量(mutable 意为 “可变的”,打破 const 限制,通常用于计数、缓存等不影响对象核心状态的场景):

class Number { 
	private: mutable int call_count = 0; // mutable 成员:可在 const 函数中修改 
	double value = 3.14; 
public: double number_value() const { 
		call_count++; // 正确:mutable 成员可修改 
		return value; 
	} 
};

5.修饰函数参数(void func(const T param))

作用:限制函数内部不能修改参数,保护实参(尤其当参数是引用/指针时)

// 1. 传值参数:const 意义不大(参数是拷贝,修改不影响实参) 
void func1(const int x) { 
	// x = 10; // 错误:不能修改 const 参数 
} 
// 2. 传引用/指针参数:意义重大(避免拷贝 + 保护实参) 
void func2(const std::vector<int>& vec) { 
	// vec.push_back(1); // 错误:不能修改实参 
}

6.修饰函数返回值(const T func())

  • 若返回值是传值(如const int func()):意义不大(返回值是临时对象,本身不可修改);
  • 若返回值是指针/引用(如const int& func()):限制调用者不能通过返回值修改原独享,避免悬垂引用/指针。
class Number { 
	private: int data = 10; 
public: 
	const int& get_data() const { // 返回 const 引用 
		return data; 
	} 
}; 
int main() { 
	Number obj; 
	// obj.get_data() = 20; // 错误:const 引用返回值不能被修改 
	return 0; 
}
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值