跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++ 基础概念速览与常见用法

这篇内容梳理了 C++ 的几个基础但容易踩坑的概念:命名空间用于避免标识符冲突,输入输出介绍了 cin、cout 和流操作符,缺省参数强调默认值必须从右往左连续设置,函数重载依赖参数列表区分,引用用于给变量取别名并简化交换逻辑,const 引用兼顾效率和只读约束,宏与内联函数对比了文本替换和函数展开的差异,最后说明了 nullptr 替代 NULL 的原因,核心是避免重载歧义。

剑仙发布于 2026/6/300 浏览
C++ 基础概念速览与常见用法

C++ 基础概念速览与常见用法

C++ 兼容 C,这意味着可以在 C++ 环境里直接写很多 C 代码。本杰尼·斯特劳斯特卢普是 C++ 之父。

命名空间

C++ 里,标识符的查找遵循作用域规则:编译器先看当前最内层作用域,找到了就停,不会再往外层找。问题也就出在这里——不同模块一旦起了同名,冲突很容易出现。

命名冲突是怎么来的

先看一个局部变量遮住库函数名的例子:

#include<stdio.h>
#include<stdlib.h>
int main() {
    int rand = 10;
    printf("%d\n", rand); // 局部变量优先,代码正确执行
}

如果把 rand 放到全局,就不一样了:

#include<stdio.h>
#include<stdlib.h>
int rand = 10; // 与 stdlib.h 中的 rand 函数冲突
int main() {
    printf("%d\n", rand); // 编译报错
}

这类问题用命名空间来隔开。

命名空间的写法

命名空间可以理解成一个带名字的容器,用来放变量、函数、类这些标识符。访问时通常写成 命名空间名::标识符。

namespace mycode {
    int rand = 10;
}

int main() {
    printf("%d\n", mycode::rand); // 正常打印 10
}

嵌套命名空间

同一个大命名空间里还可以继续分层。实际写代码时,这比硬把所有名字堆在一起更清楚。

#include<stdio.h>
namespace code {
    namespace codeA {
        int a = 10;
    }
    namespace codeB {
        int a = 20;
    }
}

int main() {
    printf("%d\n", code::codeA::a); // 打印 10
    printf("%d\n", code::codeB::a); // 打印 20
}

常见用法

除了直接写全名,还有两种方式:

  • 只引入某个成员
using name::a; // 只引入 a
  • 引入整个命名空间
using namespace name; // 引入所有成员

后者图省事,但污染也明显,尤其在头文件和公共代码里,我一般都会躲开。

C++ 允许同一个命名空间分散在多个文件里,编译器会把它们合并起来。标准库统一放在 std 命名空间中。

C++ 的输入输出

C++ 的标准输入输出头文件是 <iostream>,它提供了 cin、cout 以及流操作符 <<、>>。

cin 和 cout

std::cin 用来从控制台读数据,std::cout 用来往控制台写数据。它们都在 std 命名空间里,所以通常会写 using namespace std;,或者直接加 std:: 前缀。

流操作符

  • << 配合 cout,负责输出
  • >> 配合 cin,负责输入
#include<iostream>
using namespace std;

int main() {
    cout << "hello world" << endl;
    cout << "我的刀盾喜欢奶龙" << endl << "咕咕嘎嘎" << endl;
    
    int a, b;
    cout << "请输入两个整数:";
    cin >> a >> b;
    cout << "两个数之和为:" << a + b << endl;
}

这里最方便的地方,是不用像 C 那样手动写格式占位符,编译器会按变量类型处理。endl 会换行,并顺手刷新缓冲区。

缺省参数

缺省参数就是给函数参数一个默认值。调用时不传,就用默认值;传了,就覆盖掉。

全缺省和半缺省

  • 全缺省:所有参数都有默认值
  • 半缺省:只有部分参数有默认值

C++ 对缺省参数的顺序要求很死:必须从右往左连续设置。也就是说,左边不能空着,右边却有默认值。

#include<iostream>
using namespace std;

// 正确:缺省值从右向左
void Print(int a, int b = 1, int c = 2) {
    cout << a << "," << b << "," << c << endl;
}

int main() {
    Print(0);      // 打印 0,1,2
    Print(6, 6);   // 打印 6,6,2
    Print(5, 5, 5);// 打印 5,5,5
    // Print();    // 错误:没传够非缺省参数
}

函数声明和定义分开写时,缺省参数放在声明里更稳妥,别两边都写。

函数重载

同一个作用域里,C++ 允许出现多个同名函数,只要参数列表不同。区别可以是参数个数不同,也可以是类型或者顺序不同。

#include<iostream>
using namespace std;

// 参数个数不同
int Add(int a, int b, int c) { return a + b + c; }
int Add(int a, int b) { return a + b; }

// 参数类型不同
double Calc(int a, double b) { return a + b; }
double Calc(double a, int b) { return a - b; }

int main() {
    cout << Add(1, 1, 1) << endl; // 调用三参数版本
    cout << Add(1, 1) << endl;    // 调用两参数版本
    
    cout << Calc(2, 2.2) << endl; // 第一个是 int,第二个是 double
    cout << Calc(2.2, 2) << endl; // 第一个是 double,第二个是 int
}

这种写法比起给函数起一堆相近名字,要顺手得多。

引用

引用可以看成已有变量的别名。它不复制数据,直接绑定到原变量上,改引用就是改原变量。

引用和指针

以前交换变量常写指针版本,现在引用版本更干净:

// 指针写法
void Swap(int* a, int* b) {
    int tmp = *a;
    *a = *b;
    *b = tmp;
}

// 引用写法
void Swap(int& a, int& b) {
    int tmp = a;
    a = b;
    b = tmp;
}

引用不用写 * 解引用,读起来更像在操作普通变量。

引用的几个限制

  • 定义时必须初始化,绑定之后不能再改绑到别的对象
  • 一个变量可以有多个引用,改其中一个,原变量和其他引用都会跟着变
  • 没有空引用这一说,写起来比指针少很多边界判断

const 引用

const 引用常用来传参。它的价值很实际:既避免拷贝,又不让函数内部乱改数据。

权限控制

  • 原变量可读可写,const 引用把它限制成只读
  • 原变量本身就是 const 时,const 引用也只能读
int main() {
    int a = 3;
    const int& ra = a; // 安全,ra 只能读
    // ra = 3;        // 错误:超出权限
}

绑定临时变量

普通引用不能绑临时变量,比如字面量,因为它既短命又不可写。const 引用可以接住它,还会顺手延长生命周期。

int main() {
    const double& ra = 20; // 安全
    // int& rra = 20;      // 错误:权限放大
}

宏与内联函数

宏

宏发生在预处理阶段,本质上就是文本替换。它有无参和有参两种写法,快是快,但不受类型检查约束,优先级也容易出坑。

#define Add(a,b) ((a) + (b))

内联函数

内联函数会建议编译器把函数体展开到调用处,省掉一些函数调用开销。它保留了函数的类型检查,也比宏更好调。

特性宏内联函数
本质文本替换函数
调试无法调试可以调试
优先级需手动加括号无需处理

nullptr

C++11 引入了 nullptr,专门表示空指针,用来替代老的 NULL。

为什么要换成 nullptr

NULL 在 C++ 里通常就是 0。这在重载场景里很烦,因为它可能被当成整数,而不是空指针。

#include<iostream>
using namespace std;

void Print(int* x) { cout << "int*" << endl; }
void Print(int x) { cout << "int" << endl; }

int main() {
    Print(NULL);     // 实际调用 Print(int),因为 NULL 是 0
    Print(nullptr);  // 正确调用 Print(int*)
}

nullptr 的意思更明确,重载时也少歧义。这个改动不花哨,但很实用。

目录

  1. C++ 基础概念速览与常见用法
  2. 命名空间
  3. 命名冲突是怎么来的
  4. 命名空间的写法
  5. 嵌套命名空间
  6. 常见用法
  7. C++ 的输入输出
  8. cin 和 cout
  9. 流操作符
  10. 缺省参数
  11. 全缺省和半缺省
  12. 函数重载
  13. 引用
  14. 引用和指针
  15. 引用的几个限制
  16. const 引用
  17. 权限控制
  18. 绑定临时变量
  19. 宏与内联函数
  20. 宏
  21. 内联函数
  22. nullptr
  23. 为什么要换成 nullptr
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 2026 年 AI 发展观察:教育、商业化与主权算力
  • Python 3.12.0 的安装、环境配置与实战准备
  • 用 LLaMA-Factory 微调 Qwen3.5-4B 做医疗助手
  • Spatial Joy 2025 AR/AI 赛事参赛指南
  • 大模型训练数据争议与同质化现实
  • OpenClaw 飞书机器人部署笔记
  • Claude 4.6 的 Agent Teams 与 Python 接入思路
  • 用 AI 把网页 URL 生成 Tailwind CSS 的实战记录
  • STM32H743 用定时器触发 ADC 和 DMA 做多通道采样
  • Python 的抽象基类、协议和鸭子类型
  • 通义万相 2.1 上手与效果观察
  • SSM 与 Vue 在线投稿系统实现记录
  • 用 Consistency Decoder 提升 Stable Diffusion 画质
  • C++ 虚函数、多态与对象内存布局
  • OpenClaw 3.8 更新:ACP 溯源、备份工具和安全修复
  • 无人机检测数据集整理:11998 张图像与多格式标注
  • Web 端 3D 开发的实用技术栈梳理
  • LLM 训练怎么走:预训练、微调和 RLHF
  • 腾讯三款 AI Agent 怎么选:WorkBuddy、QClaw、CodeBuddy 实测
  • 提升 PyTorch 训练效率的 9 个实用做法

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online