Pwn 基础之C/C++(九):从 C 到 C++——类、对象与 RAII
本篇目标:理解 C++ 引用、对象、构造析构和现代资源管理。
预计阅读时间:20~25 分钟。
1. 第一个 C++ 程序
#include <iostream>
int main()
{
std::cout << "Hello, C++!" << '\n';
return 0;
}
编译:
g++ -std=c++17 -Wall -Wextra -g -O0 program.cpp -o program
std 是标准库命名空间,std::cout 是其中的输出流对象。
2. 引用
int value = 100;
int &reference = value;
reference = 200;
reference 是 value 的另一个名称,修改引用就是修改原对象。
引用声明后必须绑定到对象,普通引用不能再改为引用另一个对象。
3. 按引用传递
void change(int &value)
{
value = 100;
}
调用:
int number = 10;
change(number);
C 中通常需要使用指针:
void change(int *value);
change(&number);
C++ 引用提供了另一种表达“操作原对象”的方式。
4. 常量引用
void print_name(const std::string &name)
{
std::cout << name << '\n';
}
const T &:
- 避免复制较大对象;
- 不允许函数通过该引用修改对象;
- 常用于只读参数。
5. 函数重载
int add(int a, int b)
{
return a + b;
}
double add(double a, double b)
{
return a + b;
}
C++ 可以根据参数类型选择同名函数。编译后需要通过名称修饰区分不同签名。
6. 类与对象
#include <iostream>
#include <string>
class User {
private:
int id_;
std::string name_;
public:
void set_id(int id)
{
id_ = id;
}
int get_id() const
{
return id_;
}
void set_name(const std::string &name)
{
name_ = name;
}
void print() const
{
std::cout << id_ << ": " << name_ << '\n';
}
};
使用:
User user;
user.set_id(1);
user.set_name("Alice");
user.print();
类把数据和操作这些数据的函数组合在一起。
7. class 与 struct
C++ 中两者都能拥有成员变量、成员函数、构造函数、析构函数和继承。
主要默认区别:
class 默认 private
struct 默认 public
8. 访问控制
class Example {
public:
int public_value;
protected:
int protected_value;
private:
int private_value;
};
访问控制是编译期语言规则。private 成员仍然是对象状态的一部分。
9. this 指针
成员函数需要知道正在操作哪个对象,内部存在隐含的 this 指针:
void set_id(int id)
{
this->id_ = id;
}
this 指向当前对象。
10. 构造函数
class User {
private:
int id_;
public:
User()
: id_(0)
{
}
explicit User(int id)
: id_(id)
{
}
};
User first;
User second(10);
成员初始化列表直接初始化成员。explicit 可以阻止不希望发生的单参数隐式转换。
11. 析构函数
class Resource {
public:
Resource()
{
std::cout << "created\n";
}
~Resource()
{
std::cout << "destroyed\n";
}
};
局部对象离开作用域时会自动调用析构函数。
12. RAII
RAII:Resource Acquisition Is Initialization。
核心思想:
资源的生命周期绑定到对象生命周期。
构造时获取资源,析构时释放资源。资源可以是内存、文件、锁、连接或系统句柄。
13. new 与 delete
int *pointer = new int(100);
delete pointer;
pointer = nullptr;
数组:
int *numbers = new int[10];
delete[] numbers;
对应关系:
malloc ↔ free
new ↔ delete
new[] ↔ delete[]
new 创建对象并调用构造函数,delete 调用析构函数并释放存储。
14. 智能指针
现代 C++ 更推荐让对象自动管理动态资源:
#include <memory>
auto pointer = std::make_unique<int>(100);
离开作用域后自动释放。
std::unique_ptr:唯一所有权;std::shared_ptr:共享所有权;std::weak_ptr:观察共享对象但不增加强引用计数。
只有一个所有者时优先使用 unique_ptr。
15. 标准容器优先
手动动态数组:
int *numbers = new int[10];
多数普通业务代码中更适合:
#include <vector>
std::vector<int> numbers(10);
字符串也优先考虑:
std::string name = "Alice";
标准类型会负责其内部资源生命周期。
本篇练习
- 用引用实现整数交换。
- 创建
Student类,包含构造函数和打印函数。 - 创建对象并观察构造、析构顺序。
- 用
std::vector重写 C 动态数组练习。 - 用
std::unique_ptr管理一个自定义对象。
本篇小结
- 引用是对象的别名;
- 类组合数据和成员函数;
this指向当前对象;- 构造函数初始化对象,析构函数完成清理;
- RAII 将资源和对象生命周期绑定;
- 现代 C++ 优先使用容器和智能指针。
下一篇
最后一篇学习继承、虚函数、复制移动、标准容器、模板和反编译代码阅读基础。

说些什么吧!