一篇搞懂C++中const和指针的暧昧关系,以及函数传参的“潜规则“(附详细代码)


一篇搞懂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 = &num; // 报错!需要const int*
int* ptr = const_cast<int*>(&num); // 危险操作!
*ptr = 20; // 未定义行为(可能程序崩溃)

✅ 正确姿势:一const到底

const int num = 10;
const int* ptr1 = &num; // 安全
const int& ref1 = num;  // 安全

五、总结脑图(建议保存)

            C++的const之道
               /     \
          指针玩法    函数传参
          /  |  \      /   \
       只读 霸道 锁死 引用 指针
       const* *const 双const &与const

记住三个口诀:

  1. 想省内存用引用,加上const更安心
  2. 指针穿衣要穿好,const防护不能少
  3. 参数传递看需求,能抱(引用)就别扛(拷贝)

看完这篇还搞不懂的话…那就再看一遍吧(笑)!欢迎在评论区交流你的const迷惑经历~ 下期咱们聊聊C++的移动语义,保证同样精彩!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值