一篇搞懂C++中const和指针的暧昧关系,以及函数传参的"潜规则"(附详细代码)
大家好呀,我是灰灰,今天咱们来聊聊C++里让无数萌新抓狂的const
和指针的缠绵纠葛,还有函数传参时那些&
和const
的"小心机"。准备好瓜子饮料,咱们开车啦!
一、指针与const的"花式捆绑"(附经典姿势)
1. 只读情人模式(指向常量的指针)
const int* ptr; // 或 int const* ptr;
特点:你可以换女朋友(修改指针指向),但不能动手动脚(修改指向的值)
适用场景:查看数据但不想修改时
int a = 10, b = 20;
const int* ptr = &a;
// *ptr = 30; // 达咩!禁止修改值
ptr = &b; // 可以随时换对象(指向新地址)
2. 霸道总裁模式(常量指针)
int* const ptr;
特点:死心塌地跟定你(不能改指向),但允许你为所欲为(修改值)
适用场景:需要固定操作某个内存区域时
int a = 10;
int* const ptr = &a;
*ptr = 20; // 随便改值
// ptr = &b; // 禁止劈腿!(不能改指向)
3. 柏拉图式恋爱(双const锁死)
const int* const ptr;
特点:既不能换对象,也不能动手动脚
适用场景:只可远观不可亵玩的配置数据
const int MAX = 100;
const int* const ptr = &MAX;
// *ptr = 200; // 禁止!
// ptr = nullptr; // 也不行!
二、函数传参的"江湖规矩"(const和&的骚操作)
🚩规则1:能抱就别扛(优先用const引用)
口诀:看见大对象,先上const T&
准没错!
// 错误示范:直接扛大象(值传递)
void processBigObj(std::vector<std::string> data); // 每次调用都完整拷贝
// 正确姿势:温柔地抱(const引用)
void processBigObj(const std::vector<std::string>& data); // 零拷贝,安全无副作用
🚩规则2:想改对象?给个名分(普通引用)
void changeValue(int& num) {
num *= 2; // 直接修改原值
}
int main() {
int a = 5;
changeValue(a); // a变成10
// changeValue(5); // 报错!不能给字面量名分
}
🚩规则3:临时对象也配拥有姓名(const引用特权)
void showMessage(const std::string& msg) {
std::cout << msg << std::endl;
}
showMessage("Hello World"); // 临时字符串也能传
// 普通引用版本会报错:
// void badShow(std::string& msg);
// badShow("crash here"); // 编译错误
🚩规则4:指针参数的自我修养(附加const保护)
// 危险操作:裸指针随便玩
void dangerous(int* ptr) {
*ptr = 666; // 可能误伤重要数据
}
// 安全姿势:给指针上锁
void safeOperation(const int* ptr) {
// *ptr = 666; // 编译器会阻止
std::cout << *ptr; // 只读操作
}
三、实战技巧大放送
🔥技巧1:函数重载玩转const
class Student {
public:
// const版本给外人用
const std::string& getName() const { return name; }
// 非const版本给自己人用
std::string& getName() { return name; }
private:
std::string name;
};
🔥技巧2:返回const引用防篡改
class ConfigManager {
public:
const std::map<std::string, int>& getConfig() const {
return config; // 返回const引用防止外部修改
}
private:
std::map<std::string, int> config;
};
🔥技巧3:参数类型自动选择
void smartFunc(const std::string& s) {
// 自动兼容各种传参方式:
// 1. 字符串字面量
// 2. string对象
// 3. 其他能转为string的类型
}
四、避坑指南(血泪经验)
❌ 大坑1:const引用接临时对象后…
const std::string& badRef = "临时对象";
// 危险!临时对象销毁后引用变悬垂
❌ 大坑2:自以为是的类型转换
const int num = 10;
int* ptr = # // 报错!需要const int*
int* ptr = const_cast<int*>(&num); // 危险操作!
*ptr = 20; // 未定义行为(可能程序崩溃)
✅ 正确姿势:一const到底
const int num = 10;
const int* ptr1 = # // 安全
const int& ref1 = num; // 安全
五、总结脑图(建议保存)
C++的const之道
/ \
指针玩法 函数传参
/ | \ / \
只读 霸道 锁死 引用 指针
const* *const 双const &与const
记住三个口诀:
- 想省内存用引用,加上const更安心
- 指针穿衣要穿好,const防护不能少
- 参数传递看需求,能抱(引用)就别扛(拷贝)
看完这篇还搞不懂的话…那就再看一遍吧(笑)!欢迎在评论区交流你的const迷惑经历~ 下期咱们聊聊C++的移动语义,保证同样精彩!