前言
从 C 语言到 C++ 的转变涉及编程范式的巨大跨越。如果只关注'封装、继承、多态'而忽略基础语法差异,后续学习容易困惑。
本文旨在总结 C++ 常用但 C 语言没有的基础知识,帮助初学者理清 C 与 C++ 之间的差异。
一、namespace 是什么?
1. 情景引入
在 C 语言中,变量和函数存储于全局作用域,同名会导致冲突。例如:
#include<iostream>
using namespace std;
int test(int a) {
return a;
}
int main() {
int test = 1;
cout << test(test);
return 0;
}
上述代码编译错误,因为 test 既指函数又指变量,造成命名冲突。C++ 通过 namespace 关键字解决了这一问题。
2. 命名空间定义
使用 namespace 关键字自定义命名空间(作用域),其中可定义变量、函数或类型。
namespace a1 {
int hello = 6;
int test(int a) {
return a;
}
}
3. 命名空间的使用
有三种方式:
- 加作用限定符:使用前加空间名称和
::。int main() { cout << a1::hello; return 0; } - 引入特定成员:使用
using将某个成员引入全局作用域。using a1::hello; int main() { cout << hello; return 0; } - 引入整个空间:使用
using namespace将整个空间引入(需谨慎防止冲突)。using namespace a1; int main() { cout << hello; return 0; }
标准库中的 std 命名空间包含 <iostream>、<vector> 等头文件的声明,目的是避免名称冲突。未包含的头文件不会向 std 添加声明。
二、缺省参数
1. 概念
在声明或定义函数时,为形参预备一个值。调用时若未传实参则采用缺省值,否则使用指定实参。
#include<iostream>
using namespace std;
void fun(int a = 100) {
cout << a;
}
int main() {
fun(); // 输出 100
fun(10); // 输出 10
return 0;
}
2. 细节
- 全缺省/半缺省:所有参数有缺省值为全缺省;部分有则为半缺省。
- 位置限制:若某参数是缺省参数,其后的参数必须也是缺省参数。
- 定义限制:缺省参数不能在函数声明和定义中同时出现。
- 值限制:缺省值必须是常量或全局变量。 C 语言不支持缺省参数。
三、函数重载
1. 概念
C++ 允许在同一作用域中声明几个功能类似的同名函数,只要形参列表(个数、类型或顺序)不同即可。注意:返回值类型不参与区分。
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
int main() {
cout << add(1, 2) << endl;
cout << add(3.1, 4.2) << endl;
return 0;
}
2. 原理:名字修饰规则
C++ 编译器会对函数名进行修饰(Name Mangling),以便区分重载函数。以 Linux G++ 为例:
- 前缀
_Z表示 C++ 名称。 - 长度 + 函数名:如
3add。 - 参数类型编码:
i代表int,d代表double。
因此 add(int,int) 变为 _Z3addii,add(double,double) 变为 _Z3adddd。C 语言无此规则,故无法实现重载。
四、引用
引用是 C++ 特有的特性,C 语言中没有。
1. 概念
引用并非新变量,而是已有变量的别名,指向同一地址空间。
int main() {
int a = 1;
int& A = a;
cout << a << endl; // 输出 1
cout << A << endl; // 输出 1
}
2. 特性
- 必须初始化:定义时必须绑定实体。
- 不可更改指向:一旦引用某实体,不能再引用其他实体。
- 权限匹配:常变量只能被常引用引用;普通变量可被常引用引用(权限下降)。
3. 使用场景
1)引用传参
相比指针,引用更简洁地实现交换操作:
void swap(int& left, int& right) {
int temp = left;
left = right;
right = temp;
}
2)引用做返回值
返回局部变量的引用会导致悬空引用问题。
int& add(int a, int b) {
int c = a + b;
return c; // 危险:c 是局部变量
}
当函数结束,局部变量 c 的栈帧被销毁,返回的引用指向无效内存,属于未定义行为,访问会导致崩溃或错误结果。

