C++基础入门教程(一):基础知识大杂烩

前言


这是一篇面向初学者的 C++ 入门梳理。标题叫"大杂烩",确实是因为入门阶段需要同时建立好几条线索:程序怎么从源码变成可执行文件、变量和类型是怎么回事、控制流和函数怎么写、类为什么存在、标准库能帮我们省掉哪些重复劳动。这些内容单独看都不难,混在一起就容易只见树木不见森林。


入门阶段最常见的误解有三个。第一,把 C++ 当成"带类的 C",以为了解printf和for循环就算入门,结果一遇到std::string、引用、构造函数就卡住。第二,过早纠结语法细节,比如指针的指针、模板偏特化,却不知道标准库的std::vector和std::string已经能覆盖绝大多数日常需求。第三,照抄网上代码但不理解生命周期,写出返回局部变量引用的函数,程序在某个时刻莫名崩溃。


本文按"编译模型 → 类型与变量 → 控制流与函数 → 类 → 标准库"的顺序走一遍,每个部分只讲最核心的概念,并给出一个综合示例。代码以 C++17 为基准。文中不会声称任何代码"已经编译运行",所有结论都按标准语义描述;读者应当在本地工具链上自行验证。


一、从源码到可执行文件


C++ 是编译型语言。一个源文件大致要经过四个阶段:




阶段工具主要工作



预处理预处理器展开#include、替换宏、处理条件编译

编译编译器把翻译单元转成汇编或目标代码,做类型检查

汇编汇编器把汇编转成机器码形式的目标文件

链接链接器合并目标文件与库,解析符号,生成可执行文件



初学者最容易忽略的是"声明"与"定义"的区别。声明告诉编译器"有这么个名字,类型是这样";定义则真正分配存储或给出函数体。一个函数可以声明多次,但只能定义一次。头文件里通常放声明,源文件里放定义,原因就在这里。


最小的 C++ 程序长这样:


// 适用于 C++17
#include <iostream>

int main() {
std::cout << "Hello, C++\n";
return 0;
}

main的返回类型必须是int,void main()从来不是标准写法,某些编译器容忍它只是扩展。main函数比较特殊:不写return语句时,标准规定等价于返回 0。std::cout是标准输出流,\n是换行符,比std::endl少一次强制刷新,通常更合适。


源文件的扩展名(.cpp、.cc、.cxx)由编译器约定,标准并不规定。编译命令因工具链而异,本文不展开具体命令行参数。


二、类型、变量与初始化


C++ 是静态类型语言,每个变量在编译期就有确定的类型。常用基础类型包括int、long long、double、char、bool。标准只规定了最小范围,例如int至少 16 位,实际宽度由实现决定;sizeof(long)在 Windows 的 LLP64 模型下通常是 4 字节,在 Linux 的 LP64 模型下通常是 8 字节。写跨平台代码时不要假设具体宽度,需要固定宽度就用<cstdint>里的std::int32_t、std::int64_t。


初始化方式有好几种,推荐使用花括号初始化:


// 适用于 C++17
int a = 0; // 复制初始化
int b(0); // 直接初始化
int c{0}; // 列表初始化,推荐
double d{1.5};
bool flag{false};

花括号初始化的好处是会拒绝窄化转换。例如int x{3.14};在标准 C++ 中是编译错误,而int x = 3.14;只会悄悄截断。这类"把错误提前到编译期"的特性,入门阶段就应该养成习惯。


auto让编译器从初始化表达式推导类型,从 C++11 起可用。它减少了冗长的类型名,但不要滥用:当读者需要从代码直接看出类型时,写明确类型更清晰。const表示"初始化后不可修改",应当优先使用;它能帮助编译器优化,也能防止误改。constexpr表示"可以在编译期求值",从 C++11 起可用,C++14 起对函数体的限制放宽。


// 适用于 C++17
const int kMaxCount = 100;
constexpr int kSquare(int x) { return x * x; }
auto name = std::string{"C++"};

命名习惯上,常量常用k前缀或全大写,变量用小驼峰或下划线分隔,团队统一即可,标准不做要求。


三、控制流与函数


控制流语句与 C 类似:if/else、switch、for、while、do/while、break、continue。C++11 增加了范围for,遍历容器时非常方便:


// 适用于 C++17
std::vector<int> values{1, 2, 3, 4, 5};
int sum = 0;
for (int v : values) {
sum += v;
}
for (const auto& v : values) {
// 只读遍历,避免拷贝
}

函数由返回类型、名字、参数列表和函数体组成。C++ 支持重载:同名函数只要参数列表不同即可共存,返回类型不参与重载决议。默认参数只能从右向左连续给出。函数声明放在头文件,定义放在源文件,或者对短小的函数使用inline。


参数传递有三种常见方式,选择哪种直接影响语义和开销:




方式写法适用场景



传值void f(int x)小型平凡类型,或需要在函数内修改副本

传引用void f(std::string& s)需要修改调用方对象

传常量引用void f(const std::string& s)只读且对象较大,避免拷贝

传右值引用void f(std::string&& s)移动语义,通常配合std::move



返回局部变量的引用或指针是典型的悬垂引用,属于未定义行为。返回局部变量本身(按值)是安全的,编译器会做返回值优化或移动。


四、类与对象入门


类把数据和对数据的操作放在一起。一个最基本的类包含构造函数、成员函数和访问控制:


// 适用于 C++17
#include <string>
#include <utility>

class Rectangle {
public:
Rectangle(double width, double height)
: width_(width), height_(height) {}

double area() const { return width_ * height_; }

void scale(double factor) {
width_ *= factor;
height_ *= factor;
}

private:
double width_;
double height_;
};

这里有几个入门必须掌握的点。构造函数初始化列表按成员声明顺序执行,不是按书写顺序,所以成员初始化最好与声明顺序一致。area() const末尾的const表示该函数不修改对象状态,const 对象只能调用 const 成员函数。数据成员设为private,外部通过公开接口访问,这就是封装。


如果类需要被继承并且会通过基类指针删除派生类对象,基类析构函数必须是virtual,否则是未定义行为。类如果管理了资源(比如裸指针),要么手写析构、拷贝构造、拷贝赋值(规则三),要么用 RAII 成员让编译器生成(零规则)。现代 C++ 强烈推荐零规则:用std::string、std::vector、std::unique_ptr作为成员,不手写资源管理代码。


对象切片也值得提前知道:把派生类对象按值传给基类参数,只会保留基类部分,派生类的数据和行为丢失。需要多态时应传引用或指针。


五、标准库:先用起来,再谈原理


初学者不必急着实现容器。标准库已经提供了高质量的基础设施:



  • std::string:动态长度的字符串,替代char[]和strcpy。

  • std::vector<T>:动态数组,连续存储,随机访问 O(1),尾部追加均摊 O(1)。

  • std::array<T, N>:固定长度数组,不涉及堆分配。

  • std::map/std::unordered_map:有序/无序键值容器。

  • std::sort:排序算法,平均复杂度 O(n log n),要求比较器满足严格弱序。

  • std::iostream:输入输出流。


使用容器要包含对应头文件,并注意std::限定。不要在头文件里写using namespace std;,那会把整个命名空间塞给所有包含者。源文件里为了简短可以用,但更推荐显式写std::。


std::vector的operator[]不做边界检查,越界是未定义行为;需要检查时用at(),越界会抛std::out_of_range。size()返回的是无符号的std::size_t,与有符号整数比较时要注意转换规则,编译器通常会给出警告。


六、综合示例:统计学生成绩


下面这个程序把结构体、容器、范围 for、lambda、排序和函数组合在一起,适合作为第一阶段的练手目标。


// 适用于 C++17
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>

struct Student {
std::string name;
int score;
};

double average(const std::vector<Student>& students) {
if (students.empty()) {
return 0.0;
}
int sum = 0;
for (const auto& s : students) {
sum += s.score;
}
return static_cast<double>(sum) / static_cast<double>(students.size());
}

int main() {
std::vector<Student> students{
{"Alice", 90},
{"Bob", 75},
{"Carol", 88}
};

std::sort(students.begin(), students.end(),
[](const Student& a, const Student& b) {
return a.score > b.score;
});

for (const auto& s : students) {
std::cout << s.name << ": " << s.score << '\n';
}

std::cout << "average: " << average(students) << '\n';
return 0;
}

逐点说明。Student是聚合类型,可以用花括号按成员顺序初始化。std::vector的初始化列表构造会依次复制这些元素。std::sort的比较器返回a.score > b.score,表示降序;比较器必须满足严格弱序,用>=是常见错误,会导致未定义行为。average接收 const 引用,避免复制整个容器;先判断空容器,避免除零;把sum转成double再除,避免整数除法截断。按标准语义,输出顺序应为 Carol、Alice、Bob,平均分为 84.333...,具体小数位数由std::cout的默认精度决定。


常见坑点


❌ 写void main()。 ✅ 标准要求int main(),末尾可省略return 0;。


❌ 用int x = 3.14;做初始化,窄化转换被静默接受。 ✅ 用int x{3.14};,让编译器在窄化时报错。


❌ 返回函数内局部变量的引用或指针。 ✅ 按值返回,或返回生命周期覆盖调用方的对象。


❌ 在头文件里写using namespace std;。 ✅ 头文件用完整限定名,源文件中也优先显式写std::。


❌ 用std::vector::operator[]访问不确定是否越界的位置。 ✅ 需要检查时用at(),或先判断下标小于size()。


❌std::sort的比较器写成a.score >= b.score。 ✅ 使用严格弱序a.score > b.score,相等时返回false。


❌ 认为sizeof(long)在所有平台都是 8 字节。 ✅ 它是实现定义行为,需要固定宽度用<cstdint>的类型。


❌ 手写new[]/delete[]管理数组。 ✅ 用std::vector或std::array,让 RAII 负责释放。


总结




主题入门要点



编译模型预处理、编译、汇编、链接;声明可多次,定义只有一次

类型与初始化静态类型;优先花括号初始化;const、auto、constexpr常用

控制流与函数范围 for 遍历容器;按值/引用/const 引用按需选择

类构造函数初始化列表、const 成员函数、封装、虚析构

标准库先用std::string、std::vector、std::sort,不要重复造轮子

安全习惯不返回局部引用、不越界、比较器满足严格弱序



入门阶段最重要的不是记住所有语法,而是建立"类型—生命周期—所有权"这条主线。把这条主线抓住,后面学移动语义、智能指针、模板都会顺很多。




相关新闻

通达信DLL公式实战:用C语言实现MA均线指标

通达信DLL公式实战:用C语言实现MA均线指标

简介&#xff1a;通达信插件开发资料包&#xff0c;面向具有C语言与Windows编程基础、希望扩展通达信分析功能的开发者。资源围绕通达信C接口、MA移动平均线算法与DLL公式展开&#xff0c;展示了如何把均线计算逻辑封装为动态库函数&#xff0c;并通过通达信外部接口集成到行情…

2026/10/20 19:42:22 阅读更多 →
Docker微服务架构实战:拆分、容器网络与治理演进

Docker微服务架构实战:拆分、容器网络与治理演进

简介&#xff1a;这是一份面向开发工程师、运维工程师及架构师的Docker与微服务架构落地实战PDF书籍&#xff0c;适合正在规划或实施微服务改造的中小型技术团队阅读。全书聚焦微服务技术选型、服务拆分原则、传统应用向微服务过渡的方法论&#xff0c;并系统讲解Docker技术原理…

2026/10/20 19:42:22 阅读更多 →
Django生产级博客骨架源码:零配置启动+可部署结构

Django生产级博客骨架源码:零配置启动+可部署结构

简介&#xff1a;这是一套基于Django框架从零开始构建的个人博客网站完整源码&#xff0c;面向Python后端初学者与Web开发入门者&#xff0c;帮助学习者系统掌握Django项目结构、ORM建模、模板渲染、静态资源管理及基础部署流程。压缩包共421个文件&#xff0c;涵盖26个核心Pyt…

2026/10/20 19:41:21 阅读更多 →

最新新闻

模型量化如何影响推理性能?实战解析原理、选型与问题排查

模型量化如何影响推理性能?实战解析原理、选型与问题排查

在AI推理优化这条路上&#xff0c;量化是我见过投入产出比最高的手段。很多人以为量化就是把模型从FP32变成INT8&#xff0c;体积缩小、推理变快&#xff0c;但实操后才发现&#xff0c;AI模型量化对推理性能的影响并不只有正向&#xff1a;有时速度反而下降&#xff0c;精度却…

2026/10/20 20:20:51 阅读更多 →
基于Simulink的23自由度分布式电驱动整车动力学模型搭建与仿真

基于Simulink的23自由度分布式电驱动整车动力学模型搭建与仿真

做分布式电驱动车辆的控制&#xff0c;最头疼的问题就是你手上的整车模型到底该建多细。我这次在Matlab Simulink里完整搭了一套23自由度整车动力学模型&#xff0c;把车身六个方向的运动、四个车轮的垂向跳动、车轮旋转、转向系统、以及分布式驱动链条的扭转自由度全部拉进来了…

2026/10/20 20:20:51 阅读更多 →
用JSON和Python命令行构建个人技能管理工具:从数据建模到实践

用JSON和Python命令行构建个人技能管理工具:从数据建模到实践

1. 为什么需要技能管理工具&#xff1a;需求拆解与设计取舍上周末想更新简历&#xff0c;结果发现我根本说不清“现在到底会什么”。十几项技能分散在旧简历、脑图、收藏夹和一摞笔记本里&#xff0c;有的早已过期&#xff0c;有的只停留在“看过教程”的阶段&#xff0c;还有的…

2026/10/20 20:20:51 阅读更多 →
企业微信回调验证与AES加解密:.NET开发者接入指南

企业微信回调验证与AES加解密:.NET开发者接入指南

接手过几个企业微信自建应用的项目&#xff0c;每次新人对接时几乎都会卡在同一个地方&#xff1a;管理后台保存“接收消息服务器”配置时提示URL验证失败&#xff0c;或者明明验证过了&#xff0c;消息却一直推送不进来。这个环节看着只是填几个参数&#xff0c;背后实际上是一…

2026/10/20 20:20:51 阅读更多 →
vLLM Prefix Caching 原理:如何用 Paged KV 消除重复计算

vLLM Prefix Caching 原理:如何用 Paged KV 消除重复计算

先说一个我遇到过的情况。某个线上推理服务&#xff0c;所有请求都带着同一段两千多字的 system prompt&#xff0c;并发一上来&#xff0c;GPU 利用率看着很高&#xff0c;但真正对用户有用的计算没多少——大部分算力在一遍遍重复计算同一段内容的 K 和 V。很长一段时间里&am…

2026/10/20 20:20:51 阅读更多 →
用Design.md构建符合产品风格的原型设计:设计令牌实战指南

用Design.md构建符合产品风格的原型设计:设计令牌实战指南

上周跟某团队聊原型评审&#xff0c;对方把三个页面的设计稿拍在我面前&#xff0c;主色蓝就出现了五种&#xff0c;没有两个颜色值相同。评审会开了一个小时&#xff0c;快一半时间在争论“这个蓝到底是不是我们品牌那个蓝”。原型阶段最让人心累的从来不是画得快不快&#xf…

2026/10/20 20:19:47 阅读更多 →

日新闻

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

CLRC663芯片Pin-to-Pin替代实战:从评估到量产全记录

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
ESP32舵机控制指南:原理、多路驱动与避坑实战

ESP32舵机控制指南:原理、多路驱动与避坑实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →
位移法实现一阶低通滤波:单片机ADC采样降噪实战

位移法实现一阶低通滤波:单片机ADC采样降噪实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 1:01:30 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型&#xff08;GMM&#xff09;的语音识别系统&#xff0c;很多人第一反应就是一堆数学公式&#xff0c;觉得门槛很高。但如果你真的在MATLAB里把它落地跑通&#xff0c;会发现核心其实就是三件事&#xff1a;把声音变成特征向量&#xff0c;用GMM给每个类别…

2026/10/20 10:02:13 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人&#xff0c;但落到具体操作上&#xff0c;无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程&#xff1a;对图像做反白、改调色板、彩色转灰度&#xff0c;最后把像素数据导出成txt文件。单看每一…

2026/10/19 17:32:41 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词&#xff0c;你会发现一个很有意思的现象&#xff1a;每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型&#xff0c;有人指的是运动控制系统&#xff0c;还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/20 2:50:50 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 10:02:08 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:17 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/20 9:50:45 阅读更多 →