1 from C to C++
课程成绩
平时成绩=平时练习*0.6+期中考试*0.3+考勤*0.1
期末考试=期末实验*0.6+期末理论*0.4
总评=期末*0.6+平时*0.4
C++历史
- 面向对象的特点:
- 封装、继承和多态
- 作为抽象数据类型的类
- 易于调试和维护
- 是软件开发的主流
- 一些新增内容:
- 流式IO操作(std::cin,std::cout)
- 命名空间
- 引用
- const和constexpr
io流
初识对象
- 什么是对象
- 对象是现实世界或抽象世界中事物的一种计算机表示。
- 定义于\<iostream>中有三个对象
- cin标准输入流,使用stdout输出
- cout标准输出流,使用stdin输入
- cerr标准错误流,使用stderr输出
运算符重载
- C++的大多数运算符都可以重载:根据操作数不同,自定义运算符的操作。例如"<<"">>"是位移运算符,它左右操作数必须是整数。
- C++形象地将位移运算符用于流对象输入输出操作,例如
cout<<"hello"的含义是将hello字符放入stdout输出管道。cin>>aInt是将stdin管道输入按"%d"格式转换后放入变量。
- "<<" 重载为输出运算
- 左操作数必须是输出流对象
- 右操作数是任意类型,编译器会根据右操作数类型选择合适的 fprintf 格式化语句的版本。如右操作数是double,输出格式是"%lf"。
- 表达式返回左操作数的引用,是左值
- ">>" 重载为输入运算
- 左操作数必须是输入流对象
- 右操作数必须是左值,任意类型。编译自动根据类型使用合适 fscanf
- 表达式返回左操作数的引用,是左值
- 输入输出操纵符
- \<iostream>
- endl输出'\n'并冲洗输出流
- dec,hex,oct
- left,right
- fixed,scientific
- showpoint,noshowpoint
- showpos,noshowpos
- \<iomanip>
- setw
- setprecision
1. 基础控制 (<iostream>)
| 操纵符 |
作用 |
持续性 |
备注 |
endl |
换行 + 刷新缓冲区 |
- |
频繁使用影响性能 |
flush |
仅刷新缓冲区 |
- |
强制输出,不换行 |
ws |
(输入) 跳过前导空白 |
- |
常用于 cin >> ws |
dec |
十进制 (默认) |
✅ 持久 |
- |
hex |
十六进制 |
✅ 持久 |
配合 showbase 显示 0x |
oct |
八进制 |
✅ 持久 |
配合 showbase 显示 0 |
showbase / noshowbase |
显示/隐藏进制前缀 (0x, 0) |
✅ 持久 |
默认隐藏 |
boolalpha / noboolalpha |
布尔显示 true/false 或 1/0 |
✅ 持久 |
默认 1/0 |
showpoint / noshowpoint |
强制/隐藏显示小数点及后随零 |
✅ 持久 |
默认 noshowpoint |
uppercase / nouppercase |
十六进制/指数大写 (A-F, E) |
✅ 持久 |
默认小写 |
2. 格式排版 (<iomanip>)
| 操纵符 |
参数 |
作用 |
持续性 |
关键提示 |
setw(n) |
整数 |
设置下一个字段宽度 |
❌ 一次性 |
每列都要重写 |
setprecision(n) |
整数 |
设置精度 |
✅ 持久 |
fixed下=小数位; 默认=有效数字 |
setfill(c) |
字符 |
设置填充字符 |
✅ 持久 |
默认是空格 ' ' |
left |
无 |
左对齐 |
✅ 持久 |
配合 setw |
right |
无 |
右对齐 (默认) |
✅ 持久 |
配合 setw |
internal |
无 |
内部对齐 (符号左,数右) |
✅ 持久 |
仅对数值有效 |
fixed |
无 |
定点表示法 |
✅ 持久 |
禁止科学计数法 |
scientific |
无 |
科学计数法 |
✅ 持久 |
强制 e+ 格式 |
3. 核心口诀
- 一次性:只有
setw 是一次性的,其他大多持久。
- 精度含义:
fixed + precision = 小数位数;默认 + precision = 总有效位。
- 性能:循环输出少用
endl,多用 \n。
- 包含:带参数的必须
#include <iomanip>。
constexpr
- 含义:编译期常量表达式。
- 作用:强制编译器在编译阶段计算结果,而非运行时。
- 对比
const:
const = 运行时只读 (值可来自运行期)。
constexpr = 编译期已知 (值必须来自字面量或其他 constexpr)。
- 核心用途:
- 替代宏:定义类型安全的常量 (
constexpr int N = 10;)。
- 数组维度:
int arr[N]; (N 必须编译期已知)。
- 模板参数:
std::array<int, N>。
- 性能优化:将复杂计算移至编译期,运行时零开销。
命名空间
- 在大型项目或使用多个第三方库时,很容易出现两个不同的库定义了相同名称的函数或类的情况。例如,库 A 和库 B 都有一个叫 print() 的函数。如果没有命名空间,编译器就无法区分你调用的是哪一个,导致编译错误。
1. 核心概念
- 定义:命名空间是 C++ 中用于组织代码、避免命名冲突的机制。
- 作用:将相关的类、函数、变量等封装在特定的作用域内,防止不同库或模块间出现同名标识符冲突。
- 类比:就像文件系统中的“文件夹”,不同文件夹下可以有同名文件,通过路径区分。
基本语法
- 定义命名空间
namespace MySpace {
int value = 10;
void show() {
// 实现代码
}
class Data {
// 类定义
};
}
- 使用方式
| 方式 |
语法示例 |
特点 |
推荐度 |
| 作用域解析 |
MySpace::value |
最明确,无歧义 |
⭐⭐⭐⭐⭐ (首选) |
| using 声明 |
using MySpace::show;
show(); |
仅引入特定名称,安全 |
⭐⭐⭐⭐ |
| using 指令 |
using namespace MySpace;
value = 20; |
引入所有名称,易污染作用域 |
⭐⭐ (慎用) |
- 嵌套
- 定义:在已有的命名空间内部再定义新的命名空间,形成层级结构。
- 类比:文件系统目录结构(如
/home/user/docs),通过层级路径唯一标识资源。
- C++14及以前
namespace Company {
namespace Product {
namespace Module {
void init() {
// 实现
}
}
}
}
- C++17及以后
// C++17 新语法:等价于上面的三层嵌套
namespace Company::Product::Module {
void init() {
// ...
}
}
// 调用方式不变
Company::Product::Module::init();
引用
基本概念
- 定义:引用是某个已存在变量的别名 (Alias)。
- 本质:通过另一个名字访问同一个内存地址。
- 直观理解:给变量起“绰号”。操作别名等同于操作本体。
- 关键特性:
- ✅ 必须初始化:定义时必须绑定到一个有效变量。
- ✅ 不可重绑定:一旦绑定,终身指向该变量(不能像指针那样改指向)。
- ✅ 非空性:理论上不存在“空引用”(必须绑定对象)。
- ✅ 语法透明:使用时不需要解引用符号(如
*),像普通变量一样操作。
- 在C++中,尽可能少用指针
注意
- 引用不是对象。它们可以不占用存储,尽管若需要分配存储以实现所需语义(例如,引用类型的非静态数据成员通常会增加类的大小,量为存储内存地址所需),则由编译器具体实现决定。
- 因为引用不是对象,故
- 不存在引用的数组
- 不存在指向引用的指针
- 不存在引用的引用
- C++不存在引用为空的概念,即引用必须被定义
- 更多要掌握的关于引用概念,参见 cppreference– reference。
包括:左值引用、右值引用、转发引用、悬垂引用等。
面试经常涉及,后面课程可能并不讲解!
基本用法
type &别名 =左值表达式
int a = 10;
int &ref = a; // ref 是 a 的引用(别名)
ref = 20; // 修改 ref,实际上修改了 a
// 此时 a 的值也变成了 20
int b = 30;
// ref = b; // 错误理解!这不是让 ref 指向 b,而是把 b 的值赋给 a(因为 ref 就是 a)
作为函数返回值
int arr[10];
// 返回数组中某个元素的引用
int& getElement(int index) {
return arr[index];
}
int main() {
getElement(0) = 100; // 合法!直接修改 arr[0]
return 0;
}
注意:返回函数内部的值的引用需要静态变量
double& f( double x )
{
static double y;
y = sin(x);
return y;
}