特殊工具与技术涵盖了 C++ 中一些高级和特殊的特性,这些工具在特定场景下非常强大。
1. 控制内存分配
重载 new 和 delete
#include <new>
#include <iostream>
class MemoryDemo {
private:
static std::size_t alloc_count;
static std::size_t total_allocated;
public:
// 重载类特定的 operator new
static void* operator new(std::size_t size) {
++alloc_count;
total_allocated += size;
std::cout << "Custom new: allocating " << size
<< " bytes (total: " << total_allocated << ")" << std::endl;
if (void* ptr = ::operator new(size)) {
return ptr;
}
throw std::bad_alloc();
}
// 重载类特定的 operator delete
static void operator delete(void* ptr) noexcept {
std::cout << "Custom delete" << std::endl;
::operator delete(ptr);
}
// 重载数组版本
static void* operator new[](std::size_t size) {
std::cout << "Custom new[]: allocating " << size << " bytes" << std::endl;
return ::operator new[](size);
}
static void operator delete[](void* ptr) noexcept {
std::cout << "Custom delete[]" << std::endl;
::operator delete[](ptr);
}
// 不抛出异常的版本
static void* operator new(std::size_t size, std::nothrow_t) noexcept {
std::cout << "Custom new (nothrow)" << std::endl;
return ::operator new(size, std::nothrow);
}
static void operator delete(void* ptr, std::nothrow_t) noexcept {
std::cout << "Custom delete (nothrow)" << std::endl;
::operator delete(ptr, std::nothrow);
}
static void print_stats() {
std::cout << "Allocations: " << alloc_count
<< ", Total bytes: " << total_allocated << std::endl;
}
};
std::size_t MemoryDemo::alloc_count = 0;
std::size_t MemoryDemo::total_allocated = 0;
void memory_allocation_demo() {
MemoryDemo::print_stats();
// 使用自定义 new/delete
MemoryDemo* obj = new MemoryDemo;
delete obj;
MemoryDemo* array = new MemoryDemo[3];
delete[] array;
// 使用 nothrow 版本
MemoryDemo* nothrow_obj = new (std::nothrow) MemoryDemo;
delete nothrow_obj;
MemoryDemo::print_stats();
}
定位 new 表达式
#include <cstdlib>
class PlacementNewDemo {
private:
int value;
public:
PlacementNewDemo(int v) : value(v) {
std::cout << "Constructing PlacementNewDemo with value: " << value << std::endl;
}
~PlacementNewDemo() {
std::cout << "Destroying PlacementNewDemo with value: " << value << std::endl;
}
void print() const {
std::cout << "Value: " << value << std::endl;
}
};
void placement_new_demo() {
// 预分配内存
alignas(PlacementNewDemo) char buffer[sizeof(PlacementNewDemo)];
// 在指定内存位置构造对象
PlacementNewDemo* obj = new (buffer) PlacementNewDemo(42);
obj->print();
// 必须显式调用析构函数
obj->~PlacementNewDemo();
// 重用内存
PlacementNewDemo* obj2 = new (buffer) PlacementNewDemo(100);
obj2->print();
obj2->~PlacementNewDemo();
}
2. 运行时类型识别(RTTI)深入
typeid 操作符
#include <typeinfo>
class RTTIBase {
public:
virtual ~RTTIBase() = default;
virtual void identify() const {
std::cout << "I am RTTIBase" << std::endl;
}
};
class RTTIDerived : public RTTIBase {
public:
void identify() const override {
std::cout << "I am RTTIDerived" << std::endl;
}
void derived_method() const {
std::cout << "Derived specific method" << std::endl;
}
};
void typeid_demo() {
RTTIBase* base_ptr = new RTTIDerived;
// 使用 typeid 获取类型信息
std::cout << "typeid(*base_ptr).name(): " << typeid(*base_ptr).name() << std::endl;
std::cout << "typeid(RTTIDerived).name(): " << typeid(RTTIDerived).name() << std::endl;
// 比较类型
if (typeid(*base_ptr) == typeid(RTTIDerived)) {
std::cout << "base_ptr points to RTTIDerived object" << std::endl;
}
if (typeid(*base_ptr) != typeid(RTTIBase)) {
std::cout << "base_ptr does NOT point to RTTIBase object" << std::endl;
}
delete base_ptr;
// 内置类型的 typeid
int x = 42;
double y = 3.14;
std::cout << "typeid(int): " << typeid(x).name() << std::endl;
std::cout << "typeid(double): " << typeid(y).name() << std::endl;
}
dynamic_cast 深入
class Animal {
public:
virtual ~Animal() = default;
};
class Mammal : public virtual Animal {
public:
virtual void breathe() {
std::cout << "Mammal breathing" << std::endl;
}
};
class Winged {
public:
virtual void fly() {
std::cout << "Flying" << std::endl;
}
};
class Bat : public Mammal, public Winged {
public:
void echolocate() {
std::cout << "Bat echolocating" << std::endl;
}
};
void dynamic_cast_demo() {
Bat bat;
Animal* animal_ptr = &bat;
Mammal* mammal_ptr = &bat;
// 向上转换总是安全的
Animal* animal_from_bat = dynamic_cast<Animal*>(&bat);
// 向下转换 - 检查类型
Bat* bat_from_animal = dynamic_cast<Bat*>(animal_ptr);
if (bat_from_animal) {
std::cout << "Successful downcast from Animal to Bat" << std::endl;
bat_from_animal->echolocate();
}
// 交叉转换
Winged* winged_from_mammal = dynamic_cast<Winged*>(mammal_ptr);
if (winged_from_mammal) {
std::cout << "Successful crosscast from Mammal to Winged" << std::endl;
winged_from_mammal->fly();
}
// 引用转换(失败会抛出异常)
try {
Bat& bat_ref = dynamic_cast<Bat&>(*animal_ptr);
bat_ref.echolocate();
} catch (const std::bad_cast& e) {
std::cout << "Bad cast: " << e.what() << std::endl;
}
}
3. 类成员指针
数据成员指针
class Employee {
public:
std::string name;
int id;
double salary;
Employee(const std::string& n, int i, double s)
: name(n), id(i), salary(s) {}
void print() const {
std::cout << "Employee: " << name << " (ID: " << id
<< ", Salary: " << salary << ")" << std::endl;
}
};
void data_member_pointer_demo() {
Employee emp("John Doe", 123, 75000.0);
// 定义成员指针
std::string Employee::*name_ptr = &Employee::name;
int Employee::*id_ptr = &Employee::id;
double Employee::*salary_ptr = &Employee::salary;
// 通过成员指针访问
std::cout << "Name: " << emp.*name_ptr << std::endl;
std::cout << "ID: " << emp.*id_ptr << std::endl;
std::cout << "Salary: " << emp.*salary_ptr << std::endl;
// 通过指针访问
Employee* emp_ptr = &emp;
std::cout << "Via pointer - Name: " << emp_ptr->*name_ptr << std::endl;
// 成员指针数组
using MemberPtr = std::string Employee::*;
MemberPtr members[] = {&Employee::name};
for (auto ptr : members) {
std::cout << "Array access: " << emp.*ptr << std::endl;
}
}
成员函数指针
class Calculator {
public:
double add(double a, double b) const {
return a + b;
}
double multiply(double a, double b) const {
return a * b;
}
double divide(double a, double b) const {
if (b == 0) throw std::invalid_argument("Division by zero");
return a / b;
}
static double static_method(double x) {
return x * x;
}
};
void member_function_pointer_demo() {
Calculator calc;
// 成员函数指针类型
using MemberFuncPtr = double (Calculator::*)(double, double) const;
// 定义成员函数指针
MemberFuncPtr add_ptr = &Calculator::add;
MemberFuncPtr multiply_ptr = &Calculator::multiply;
MemberFuncPtr divide_ptr = &Calculator::divide;
// 通过成员函数指针调用
std::cout << "5 + 3 = " << (calc.*add_ptr)(5, 3) << std::endl;
std::cout << "5 * 3 = " << (calc.*multiply_ptr)(5, 3) << std::endl;
std::cout << "6 / 2 = " << (calc.*divide_ptr)(6, 2) << std::endl;
// 静态成员函数指针
using StaticFuncPtr = double (*)(double);
StaticFuncPtr static_ptr = &Calculator::static_method;
std::cout << "static_method(4) = " << static_ptr(4) << std::endl;
// 成员函数指针表
struct Operation {
std::string name;
MemberFuncPtr func;
};
Operation operations[] = {
{"Addition", &Calculator::add},
{"Multiplication", &Calculator::multiply},
{"Division", &Calculator::divide}
};
for (const auto& op : operations) {
try {
double result = (calc.*op.func)(10, 2);
std::cout << op.name << ": " << result << std::endl;
} catch (const std::exception& e) {
std::cout << op.name << " failed: " << e.what() << std::endl;
}
}
}
4. 嵌套类
基本嵌套类
class LinkedList {
private:
struct Node {
int data;
Node* next;
Node(int value) : data(value), next(nullptr) {}
};
Node* head;
std::size_t size;
public:
// 嵌套迭代器类
class Iterator {
private:
Node* current;
public:
Iterator(Node* node) : current(node) {}
// 解引用操作符
int& operator*() {
return current->data;
}
// 前置递增
Iterator& operator++() {
if (current) {
current = current->next;
}
return *this;
}
// 后置递增
Iterator operator++(int) {
Iterator temp = *this;
++(*this);
return temp;
}
// 比较操作符
bool operator==(const Iterator& other) const {
return current == other.current;
}
bool operator!=(const Iterator& other) const {
return !(*this == other);
}
};
public:
LinkedList() : head(nullptr), size(0) {}
~LinkedList() {
while (head) {
Node* temp = head;
head = head->next;
delete temp;
}
}
void push_front(int value) {
Node* new_node = new Node(value);
new_node->next = head;
head = new_node;
++size;
}
// 迭代器接口
Iterator begin() {
return Iterator(head);
}
Iterator end() {
return Iterator(nullptr);
}
std::size_t get_size() const {
return size;
}
};
void nested_class_demo() {
LinkedList list;
list.push_front(3);
list.push_front(2);
list.push_front(1);
std::cout << "LinkedList contents: ";
for (LinkedList::Iterator it = list.begin(); it != list.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用范围for循环(需要合适的begin/end)
std::cout << "Using auto: ";
for (auto it = list.begin(); it != list.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
}
5. 位域
位域的基本使用
class BitFieldDemo {
private:
// 位域声明
unsigned int is_ready : 1; // 1 bit
unsigned int priority : 3; // 3 bits (0-7)
unsigned int status : 2; // 2 bits (0-3)
unsigned int : 2; // 未命名的填充位
unsigned int counter : 8; // 8 bits (0-255)
public:
BitFieldDemo() : is_ready(0), priority(0), status(0), counter(0) {}
void set_ready(bool ready) {
is_ready = ready ? 1 : 0;
}
bool get_ready() const {
return is_ready != 0;
}
void set_priority(unsigned int prio) {
if (prio > 7) prio = 7; // 限制在3位范围内
priority = prio;
}
unsigned int get_priority() const {
return priority;
}
void set_status(unsigned int stat) {
if (stat > 3) stat = 3; // 限制在2位范围内
status = stat;
}
unsigned int get_status() const {
return status;
}
void increment_counter() {
if (counter < 255) {
++counter;
}
}
unsigned int get_counter() const {
return counter;
}
void print() const {
std::cout << "Ready: " << get_ready()
<< ", Priority: " << get_priority()
<< ", Status: " << get_status()
<< ", Counter: " << get_counter() << std::endl;
}
};
void bitfield_demo() {
BitFieldDemo demo;
demo.print();
demo.set_ready(true);
demo.set_priority(5);
demo.set_status(2);
for (int i = 0; i < 10; ++i) {
demo.increment_counter();
}
demo.print();
// 大小信息
std::cout << "Size of BitFieldDemo: " << sizeof(BitFieldDemo)
<< " bytes" << std::endl;
}
6. volatile 限定符
volatile 的使用
class VolatileDemo {
private:
volatile int sensor_value; // 可能被硬件修改
volatile bool data_ready; // 可能被中断服务程序修改
public:
VolatileDemo() : sensor_value(0), data_ready(false) {}
// 模拟硬件读取
int read_sensor() {
// 模拟传感器值变化
return ++sensor_value;
}
// 等待数据就绪
void wait_for_data() {
while (!data_ready) {
// 空循环 - 编译器不会优化掉对volatile变量的检查
}
std::cout << "Data is ready!" << std::endl;
}
// 设置数据就绪标志
void set_data_ready() {
data_ready = true;
}
// 演示volatile在内存映射IO中的使用
void memory_mapped_io_demo() {
// 假设这是硬件寄存器地址
volatile uint32_t* hardware_register = reinterpret_cast<volatile uint32_t*>(0x12345678);
// 读取硬件寄存器
uint32_t status = *hardware_register;
// 写入硬件寄存器
*hardware_register = 0xABCD;
std::cout << "Hardware register demo completed" << std::endl;
}
};
void volatile_demo() {
VolatileDemo demo;
// 演示多次读取volatile变量
std::cout << "Sensor readings: ";
for (int i = 0; i < 5; ++i) {
std::cout << demo.read_sensor() << " ";
}
std::cout << std::endl;
// 在另一个线程中设置数据就绪标志
std::thread setter([&demo]() {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
demo.set_data_ready();
});
demo.wait_for_data();
setter.join();
}
7. 链接指示符:extern “C”
C 和 C++ 混合编程
// C 头文件模拟 (math_utils.h)
#ifdef __cplusplus
extern "C" {
#endif
// C 风格的函数声明
double c_sqrt(double x);
double c_power(double base, double exponent);
void c_print_message(const char* message);
#ifdef __cplusplus
}
#endif
// C++ 实现使用 C 函数
void extern_c_demo() {
std::cout << "Using C functions from C++:" << std::endl;
// 调用 C 函数
double result1 = c_sqrt(25.0);
double result2 = c_power(2.0, 3.0);
std::cout << "sqrt(25) = " << result1 << std::endl;
std::cout << "2^3 = " << result2 << std::endl;
c_print_message("Hello from C++!");
}
// 模拟 C 函数的实现
extern "C" {
double c_sqrt(double x) {
return sqrt(x);
}
double c_power(double base, double exponent) {
return pow(base, exponent);
}
void c_print_message(const char* message) {
std::cout << "C function says: " << message << std::endl;
}
}
8. 实践项目:内存池分配器
#include <memory>
#include <vector>
template<typename T>
class MemoryPool {
private:
struct Block {
union {
T object;
Block* next;
};
};
std::vector<std::unique_ptr<Block[]>> chunks;
Block* free_list;
std::size_t chunk_size;
void allocate_chunk() {
auto new_chunk = std::make_unique<Block[]>(chunk_size);
chunks.push_back(std::move(new_chunk));
// 将新块添加到空闲列表
for (std::size_t i = 0; i < chunk_size; ++i) {
chunks.back()[i].next = free_list;
free_list = &chunks.back()[i];
}
}
public:
MemoryPool(std::size_t chunk_size = 64)
: free_list(nullptr), chunk_size(chunk_size) {}
// 禁用拷贝
MemoryPool(const MemoryPool&) = delete;
MemoryPool& operator=(const MemoryPool&) = delete;
template<typename... Args>
T* construct(Args&&... args) {
if (!free_list) {
allocate_chunk();
}
Block* block = free_list;
free_list = free_list->next;
// 在内存位置构造对象
return new (&block->object) T(std::forward<Args>(args)...);
}
void destroy(T* object) {
// 调用析构函数
object->~T();
// 将内存块返回给空闲列表
Block* block = reinterpret_cast<Block*>(object);
block->next = free_list;
free_list = block;
}
std::size_t chunk_count() const {
return chunks.size();
}
};
// 测试类
class PooledObject {
private:
int id;
std::string name;
public:
PooledObject(int i = 0, const std::string& n = "")
: id(i), name(n) {
std::cout << "Constructing PooledObject " << id << std::endl;
}
~PooledObject() {
std::cout << "Destroying PooledObject " << id << std::endl;
}
void print() const {
std::cout << "PooledObject: id=" << id << ", name=" << name << std::endl;
}
};
void memory_pool_demo() {
MemoryPool<PooledObject> pool;
// 使用内存池分配对象
PooledObject* obj1 = pool.construct(1, "First");
PooledObject* obj2 = pool.construct(2, "Second");
PooledObject* obj3 = pool.construct(3, "Third");
obj1->print();
obj2->print();
obj3->print();
std::cout << "Chunks allocated: " << pool.chunk_count() << std::endl;
// 返回到内存池
pool.destroy(obj1);
pool.destroy(obj2);
pool.destroy(obj3);
// 重用内存
PooledObject* obj4 = pool.construct(4, "Reused");
obj4->print();
}
最佳实践总结
- 谨慎重载 new/delete,确保正确性
- 合理使用 RTTI,优先考虑虚函数
- 位域适合存储标志和状态信息
- volatile 用于硬件访问和信号处理
- extern “C” 用于 C/C++ 混合编程
1409

被折叠的 条评论
为什么被折叠?



