第二章:C++基础:从C到C++的进化

说实话,我当年从C转向C++的时候,心里是有点抵触的。总觉得C已经够用了,干嘛要学那些花里胡哨的东西?直到我在一个大型项目中,被一堆函数指针和内存管理搞得焦头烂额,才真正体会到C++带来的改变。这一章,我们就聊聊C++到底在C的基础上进化了什么。

2.1 引用与指针的区别

很多初学者会问:引用和指针到底有啥区别?说白了,引用就是一个“自动解引用的指针”。但实际用起来,差别可大了去了。

核心区别一览

特性 指针 引用
是否可为空 可以(NULL) 必须初始化,不能为空
能否重新绑定 可以 不能
内存占用 通常8字节(64位) 不占额外空间(别名)
语法糖 需要 * 和 & 像普通变量一样使用

我个人习惯在函数参数传递时,优先使用引用。为什么呢?你想想看,指针可能为空,每次用之前都得检查一下,多麻烦。引用就没这个烦恼。

// 指针版本:需要检查空指针
void process(int* p) {
    if (p == nullptr) return;  // 烦不烦?
    *p = 42;
}

// 引用版本:干净利落
void process(int& r) {
    r = 42;  // 直接干,不用操心
}

我的经验:在实现拷贝构造函数和赋值运算符时,参数一定要用 const 引用。我在项目中见过有人用指针传参,结果忘了检查空指针,线上崩溃了。嗯,那场面...挺尴尬的。

2.2 const的深度解析

const 这个关键字,看着简单,用起来门道不少。我见过很多代码,const 用得乱七八糟的。其实只要记住一个原则:const 修饰的是它左边的东西

const int* p;   // p 指向的值不能改
int* const p;   // p 本身不能改(指向不能变)
const int* const p; // 两者都不能改

为什么会这样?因为 C++ 的声明语法是“从右向左读”的。嗯,这里要注意,const 出现在类型左边和右边,效果是一样的:

const int a = 10;  // 等价于
int const a = 10;  // 一样的效果

避坑指南:我曾经在一个项目中,把 const 成员函数写成了非 const,结果导致整个模块的 const 正确性全乱了。记住:const 成员函数不能修改成员变量(除非变量被 mutable 修饰)。

const 还有一个妙用:修饰函数返回值。比如返回一个内部数组的指针,用 const 可以防止外部修改:

class Buffer {
    char data[1024];
public:
    const char* getData() const { return data; }
};

这样调用方就只能读,不能写。安全多了,对吧?

2.3 函数重载与默认参数

函数重载,说白了就是“同名不同参”。C 语言不支持这个,但 C++ 可以。编译器会根据参数类型和个数,自动匹配最合适的版本。

void print(int i) { cout << "整数: " << i << endl; }
void print(double d) { cout << "浮点数: " << d << endl; }
void print(const char* s) { cout << "字符串: " << s << endl; }

调用的时候,编译器会自动选择:

print(42);      // 调用 int 版本
print(3.14);    // 调用 double 版本
print("hello"); // 调用 const char* 版本

注意:重载不能只看返回值类型。比如下面这样是不行的:

int foo();
double foo();  // 编译错误!

因为调用时无法区分。

默认参数就更有意思了。它允许你在声明函数时给参数一个默认值:

void connect(const char* host, int port = 8080) {
    // 连接服务器
}

connect("localhost");      // 使用默认端口 8080
connect("server.com", 443); // 指定端口 443

我个人建议:默认参数放在声明里,不要放在定义里。否则容易出问题:

// 头文件(声明)
void func(int a, int b = 10);

// 源文件(定义)
void func(int a, int b) {  // 这里不要写默认值
    // ...
}

我的习惯:默认参数和函数重载可以配合使用。比如一个函数有多个参数需要默认值,用重载可能更清晰。但别滥用,否则代码会变得难以理解。

本章知识体系

下面这张图,是我梳理的本章核心知识点之间的关系:

C++ 基础进化 引用与指针 • 引用不能为空 • 指针可以重新绑定 • 引用是别名 • 指针需要解引用 const 深度解析 • 修饰左边的内容 • const 成员函数 • const 返回值 • mutable 修饰符 函数重载与默认参数 • 同名不同参 • 默认参数在声明 • 不能只看返回值 • 配合使用更灵活 核心思想:C++ 在 C 的基础上增加了类型安全和抽象能力 让代码更安全、更易维护、更高效

这张图把本章的三个核心知识点串起来了。你看,引用与指针解决的是“怎么传数据”的问题,const 解决的是“怎么保护数据”的问题,函数重载和默认参数解决的是“怎么让接口更友好”的问题。三者相辅相成,共同构成了 C++ 基础的核心。

总结一下:从 C 到 C++,不是简单的语法升级,而是一种编程思维的转变。引用让传参更安全,const 让接口更严谨,重载和默认参数让代码更灵活。这些特性用好了,代码质量能上一个台阶。

好了,这一章就到这里。记住我上面说的那些坑,写代码的时候多留个心眼。下一章我们聊聊类和对象,那才是 C++ 真正精彩的地方。

公众号:蓝海资料掘金营,微信deep3321