第二章:开始学习 C++ | C++ Primer Plus 重点带看
常用编译指令
C++ 中常见的预处理与编译指令:
#include:引入头文件,将指定文件内容插入到当前位置。
#define:宏定义,用于定义常量、宏替换等编译期替换。
using:命名空间声明,简化代码中名称的使用(如 using namespace std;)。
语句和分号
语句是程序中要执行的具体操作。为理解源代码,编译器必须依靠明确的结束标记区分语句边界。
C++ 继承了 C 语言的规则:使用分号 ; 作为语句结束符。
重要规则:
- 分号是语句的必要组成部分,不可省略。
- 缺少分号会直接导致编译报错。
关于 mian() 函数的返回值细节
main() 是程序入口函数,有一个特殊规则:
如果编译器执行到 main() 末尾,没有遇到显式 return 语句,会自动隐式补充 return 0; 。
这意味着:
- 在 main() 中,return 0; 可以省略。
- 但注意:该规则仅适用于 main(),其他任何函数都必须显式写返回语句,否则属于未定义行为。
main( ) 的返回值并不是返回给程序的其他部分,而是返回给操作系统。通常的约定是,退出值为 0 则意味着程序运行成功,为非零则意味着存在问题。
关于注释的使用 tips
单行注释 // 本才是 C++ 的注释,多行注释 /* */ 是 C 的注释。不过在后来的标准中,这两种注释都已经在 C 和 C++ 中支持了。
但注意,还是要尽量多使用 //,少使用 /* */,因为多行注释涉及到结尾符号与起始符号的正确配对。若嵌套或遗漏结束符,极易引发大面积代码注释失效。
预处理器
编译前的“预处理工具”,在编译器正式翻译代码前自动运行。
处理名称以 # 开头的编译指令。它不执行任何特殊操作,仅负责文本替换。
名称空间
名称空间是 C++ 用于解决命名冲突的核心特性,让不同厂商 / 模块的同名函数、类或变量可以共存,同时方便组织大型程序代码。
1. 为什么需要名称空间?
如果两个库都定义了同名函数(如 wanda()),编译器无法区分版本。通过名称空间封装:
Microflop::wanda("go dancing?"); // 调用 Microflop 版本
Piscine::wanda("a fish named Desire"); // 调用 Piscine 版本
2. 三种使用方式
完整限定名 |
| 最严谨,无命名冲突风险 |
using 声明(推荐) |
| 只引入需要的名称,兼顾简洁与安全 |
using 指令(偷懒写法) |
| 引入整个 |
// 特点:写法最简洁,但全局引入,大型项目易引发命名冲突。
#include <iostream>
// 全局作用域,本文件所有函数都可直接使用 std 成员
using namespace std;
void simon(int n) {
cout << "Simon says touch your toes " << n << " times." << endl;
}
int main() {
simon(3);
cout << "Pick an integer: ";
int count;
cin >> count;
simon(count);
cout << "Done!" << endl;
return 0;
}
// 特点:缩小作用范围,只有 main() 能直接用 std,更安全。
#include <iostream>
void simon(int n) {
// simon 函数内无法直接使用 cout/endl
std::cout << "Simon says touch your toes " << n << " times." << std::endl;
}
int main() {
// 仅在 main() 函数内引入 std
using namespace std;
simon(3);
cout << "Pick an integer: ";
int count;
cin >> count;
simon(count);
cout << "Done!" << endl;
return 0;
}
// 特点:兼顾简洁与安全,是工程实践中推荐的写法。
#include <iostream>
// 只引入需要的 cout/endl/cin,不引入整个 std
using std::cout;
using std::endl;
using std::cin;
void simon(int n) {
cout << "Simon says touch your toes " << n << " times." << endl;
}
int main() {
simon(3);
cout << "Pick an integer: ";
int count;
cin >> count;
simon(count);
cout << "Done!" << endl;
return 0;
}
// 特点:最严谨,完全避免命名冲突,适合大型项目和库开发。
#include <iostream>
// 不使用任何 using 指令,全程用 std:: 前缀
void simon(int n) {
std::cout << "Simon says touch your toes " << n << " times." << std::endl;
}
int main() {
simon(3);
std::cout << "Pick an integer: ";
int count;
std::cin >> count;
simon(count);
std::cout << "Done!" << std::endl;
return 0;
}
控制符 endl 与 换行符 '\n' 区别
endl 和 \n 都能实现换行,但行为完全不同,这是 C++ 初学者最容易忽略的关键点。
1、 \n(换行符)
仅表示换行,属于普通字符。
不会强制刷新输出缓冲区,输出内容可能暂存在缓冲区中,不立即显示。
2、endl(控制符)
等价于:换行 + 强制刷新缓冲区(flush)。
一定会把缓冲区内容立即输出到屏幕 / 文件,保证在后续代码执行前显示。
int number = -1; cout<<"Please enter a number(0-9)\n"; // 有些系统会在用户输入之后才会显示出提示信息 cin>>number; int number = -1; cout<<"Please enter a number(0-9)"<<endl; // 一定会在用户输入之前显示出提示信息 cin>>number;
声明语句
完整称为定义声明语句,简称定义。
作用:告诉编译器变量的类型与名字,并为其分配内存空间。
变量声明
C++ 提倡就近声明:在变量第一次使用前才定义,而不是在函数开头统一声明。(这一点与 C 语言不同)
初始化
定义变量的同时直接赋值,称为初始化。
- 声明 + 赋值一步完成。
- 比 “先定义、后赋值” 更安全、更高效。
int a = 10; // 初始化 int b; b = 20;// 先定义,后赋值(不推荐)
C++ Primer Plus 精读|从入门到面试,重点内容全程带看。 本专栏以《C++ Primer Plus》为蓝本,逐章提炼必考知识点、易错点、面试高频考点,跳过冗余示例,直击语法本质与工程实践,帮你高效吃透 C++ 基础,夯实底层开发必备能力。
查看6道真题和解析