C++ Primer 第19章:特殊工具与技术

C++ Primer 第19章:特殊工具与技术


19.1 控制内存分配

19.1.1 重载 new 和 delete

复制代码
// overload_new_delete.cpp -- 重载new和delete
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <stdexcept>
​
// ===== 全局 new/delete 重载 =====
// 通常不建议重载全局版本,会影响所有内存分配
​
// ===== 类级别的 new/delete 重载 =====
class MyClass
{
public:
    MyClass(int v = 0) : val_(v)
    {
        std::cout << "[构造] val=" << val_ << std::endl;
    }
​
    ~MyClass()
    {
        std::cout << "[析构] val=" << val_ << std::endl;
    }
​
    // 重载 operator new:分配内存
    static void* operator new(std::size_t size)
    {
        std::cout << "[new] 分配 " << size << " 字节" << std::endl;
        void* p = std::malloc(size);
        if (!p) throw std::bad_alloc();
        return p;
    }
​
    // 重载 operator delete:释放内存
    static void operator delete(void* p, std::size_t size) noexcept
    {
        std::cout << "[delete] 释放 " << size << " 字节" << std::endl;
        std::free(p);
    }
​
    // 重载数组版本
    static void* operator new[](std::size_t size)
    {
        std::cout << "[new[]] 分配 " << size << " 字节" << std::endl;
        void* p = std::malloc(size);
        if (!p) throw std::bad_alloc();
        return p;
    }
​
    static void operator delete[](void* p, std::size_t size) noexcept
    {
        std::cout << "[delete[]] 释放 " << size << " 字节" << std::endl;
        std::free(p);
    }
​
    int val() const { return val_; }
​
private:
    int val_;
};
​
int main()
{
    using namespace std;
​
    cout << "===== 单个对象 =====" << endl;
    MyClass* p = new MyClass(42);   // 调用 operator new,然后构造函数
    cout << "val = " << p->val() << endl;
    delete p;   // 调用析构函数,然后 operator delete
​
    cout << "\n===== 对象数组 =====" << endl;
    MyClass* arr = new MyClass[3];   // 调用 operator new[]
    delete[] arr;                    // 调用 operator delete[]
​
    return 0;
}

19.1.2 定位 new(placement new)

复制代码
// placement_new.cpp -- 定位new
#include <iostream>
#include <new>
#include <string>
​
class Widget
{
public:
    Widget(const std::string& name) : name_(name)
    {
        std::cout << "[构造] " << name_ << std::endl;
    }
    ~Widget()
    {
        std::cout << "[析构] " << name_ << std::endl;
    }
    void show() const { std::cout << "Widget: " << name_ << std::endl; }
​
private:
    std::string name_;
};
​
int main()
{
    using namespace std;
​
    // ===== 定位new:在指定内存上构造对象 =====
    // 语法:new (地址) 类型(参数)
​
    // 在栈上分配内存
    alignas(Widget) char buffer[sizeof(Widget)];
​
    // 在 buffer 上构造 Widget(不分配内存)
    Widget* p = new (buffer) Widget("栈上的Widget");
    p->show();
​
    // 必须手动调用析构函数!(不能用 delete)
    p->~Widget();
​
    // ===== 在堆上预分配内存,然后构造 =====
    void* raw = ::operator new(sizeof(Widget));   // 只分配内存
    Widget* p2 = new (raw) Widget("堆上的Widget");
    p2->show();
    p2->~Widget();                // 手动析构
    ::operator delete(raw);       // 手动释放内存
​
    // ===== 对象池示例 =====
    cout << "\n===== 对象池 =====" << endl;
    const int POOL_SIZE = 3;
    alignas(Widget) char pool[sizeof(Widget) * POOL_SIZE];
​
    // 在池中构造多个对象
    Widget* widgets[POOL_SIZE];
    for (int i = 0; i < POOL_SIZE; i++)
    {
        widgets[i] = new (pool + i * sizeof(Widget))
                     Widget("池对象" + to_string(i));
    }
​
    for (int i = 0; i < POOL_SIZE; i++)
        widgets[i]->show();
​
    // 手动析构(逆序)
    for (int i = POOL_SIZE - 1; i >= 0; i--)
        widgets[i]->~Widget();
​
    return 0;
}

19.2 运行时类型识别(RTTI)

19.2.1 dynamic_cast

复制代码
// dynamic_cast_demo.cpp -- dynamic_cast详解
#include <iostream>
#include <memory>
#include <string>
​
class Shape
{
public:
    virtual double area() const = 0;
    virtual std::string name() const = 0;
    virtual ~Shape() {}
};
​
class Circle : public Shape
{
public:
    Circle(double r) : radius_(r) {}
    double area() const override { return 3.14159 * radius_ * radius_; }
    std::string name() const override { return "Circle"; }
    double radius() const { return radius_; }
​
private:
    double radius_;
};
​
class Rectangle : public Shape
{
public:
    Rectangle(double w, double h) : w_(w), h_(h) {}
    double area() const override { return w_ * h_; }
    std::string name() const override { return "Rectangle"; }
    double width()  const { return w_; }
    double height() const { return h_; }
​
private:
    double w_, h_;
};
​
int main()
{
    using namespace std;
​
    Shape* shapes[] = {
        new Circle(5.0),
        new Rectangle(4.0, 6.0),
        new Circle(3.0)
    };
​
    cout << "===== dynamic_cast 指针版本 =====" << endl;
    for (auto s : shapes)
    {
        cout << s->name() << " 面积=" << s->area() << endl;
​
        // 向下转型:成功返回有效指针,失败返回 nullptr
        if (Circle* c = dynamic_cast<Circle*>(s))
        {
            cout << "  半径=" << c->radius() << endl;
        }
        else if (Rectangle* r = dynamic_cast<Rectangle*>(s))
        {
            cout << "  宽=" << r->width() << " 高=" << r->height() << endl;
        }
    }
​
    cout << "\n===== dynamic_cast 引用版本 =====" << endl;
    // 引用版本:失败时抛出 std::bad_cast
    try
    {
        Shape& s = *shapes[0];   // Circle
        Circle& c = dynamic_cast<Circle&>(s);   // 成功
        cout << "Circle半径:" << c.radius() << endl;
​
        Shape& s2 = *shapes[1];   // Rectangle
        Circle& c2 = dynamic_cast<Circle&>(s2);   // 失败!抛出 bad_cast
    }
    catch (const bad_cast& e)
    {
        cout << "bad_cast:" << e.what() << endl;
    }
​
    for (auto s : shapes) delete s;
    return 0;
}

19.2.2 typeid 运算符

复制代码
// typeid_demo.cpp -- typeid运算符
#include <iostream>
#include <typeinfo>
#include <string>
​
class Base
{
public:
    virtual ~Base() {}
    virtual std::string type() const { return "Base"; }
};
​
class Derived : public Base
{
public:
    std::string type() const override { return "Derived"; }
};
​
int main()
{
    using namespace std;
​
    // ===== typeid 基本用法 =====
    int    i = 42;
    double d = 3.14;
    string s = "Hello";
​
    // typeid 返回 type_info 对象的引用
    cout << "int:    " << typeid(i).name() << endl;
    cout << "double: " << typeid(d).name() << endl;
    cout << "string: " << typeid(s).name() << endl;
​
    // ===== typeid 与多态 =====
    cout << "\n===== 多态类型 =====" << endl;
    Base b;
    Derived d2;
    Base* p1 = &b;
    Base* p2 = &d2;
​
    // 对指针使用 typeid:返回指针类型(不是所指对象的类型)
    cout << "typeid(p1): " << typeid(p1).name() << endl;   // Base*
​
    // 对解引用指针使用 typeid:返回实际对象类型(动态类型)
    cout << "typeid(*p1): " << typeid(*p1).name() << endl;  // Base
    cout << "typeid(*p2): " << typeid(*p2).name() << endl;  // Derived
​
    // ===== 类型比较 =====
    cout << "\n===== 类型比较 =====" << endl;
    cout << boolalpha;
    cout << "p1指向Base:" << (typeid(*p1) == typeid(Base)) << endl;
    cout << "p2指向Derived:" << (typeid(*p2) == typeid(Derived)) << endl;
    cout << "p1和p2类型相同:" << (typeid(*p1) == typeid(*p2)) << endl;
​
    // ===== 实际应用:类型安全的操作 =====
    cout << "\n===== 类型安全操作 =====" << endl;
    Base* shapes[] = {new Base(), new Derived(), new Base()};
​
    for (auto s : shapes)
    {
        if (typeid(*s) == typeid(Derived))
            cout << "这是Derived对象" << endl;
        else
            cout << "这是Base对象" << endl;
        delete s;
    }
​
    return 0;
}

19.3 枚举类型

复制代码
// enum_types.cpp -- 枚举类型
#include <iostream>
#include <string>
​
// ===== 传统枚举(不限定作用域)=====
enum Color { RED, GREEN, BLUE };   // RED=0, GREEN=1, BLUE=2
enum Status { ACTIVE, INACTIVE };
​
// ⚠️ 传统枚举的问题:
// 1. 枚举值泄漏到外层作用域
// 2. 不同枚举类型可以比较(隐式转换为int)
// 3. 不能指定底层类型(默认int)
​
// ===== 限定作用域的枚举(C++11)=====
enum class Direction { NORTH, SOUTH, EAST, WEST };
enum class Permission : uint8_t   // 指定底层类型
{
    NONE    = 0,
    READ    = 1,
    WRITE   = 2,
    EXECUTE = 4,
    ALL     = READ | WRITE | EXECUTE
};
​
// ===== 枚举的前置声明(C++11)=====
enum class Season : int;   // 前置声明
void printSeason(Season s);
​
enum class Season : int { SPRING, SUMMER, AUTUMN, WINTER };
​
void printSeason(Season s)
{
    switch (s)
    {
        case Season::SPRING: std::cout << "春天" << std::endl; break;
        case Season::SUMMER: std::cout << "夏天" << std::endl; break;
        case Season::AUTUMN: std::cout << "秋天" << std::endl; break;
        case Season::WINTER: std::cout << "冬天" << std::endl; break;
    }
}
​
int main()
{
    using namespace std;
​
    // 传统枚举
    Color c = RED;
    int n = c;   // ✅ 隐式转换为int
    // Color c2 = 0;   // ❌ 不能从int转换
​
    // 不同枚举类型可以比较(危险!)
    // if (RED == ACTIVE) {}   // 编译通过,但语义错误
​
    // 限定作用域枚举
    Direction d = Direction::NORTH;
    // int m = d;   // ❌ 不能隐式转换
    int m = static_cast<int>(d);   // ✅ 必须显式转换
​
    // 不同枚举类型不能比较
    // if (Direction::NORTH == Season::SPRING) {}   // ❌ 编译错误
​
    // 权限枚举
    Permission perm = Permission::READ;
    cout << "READ = " << static_cast<int>(perm) << endl;
​
    // 使用位运算(需要显式转换)
    auto combined = static_cast<Permission>(
        static_cast<uint8_t>(Permission::READ) |
        static_cast<uint8_t>(Permission::WRITE));
    cout << "READ|WRITE = " << static_cast<int>(combined) << endl;
​
    // 季节枚举
    printSeason(Season::AUTUMN);
​
    // 枚举的大小
    cout << "\n枚举大小:" << endl;
    cout << "Color: " << sizeof(Color) << " 字节" << endl;
    cout << "Permission: " << sizeof(Permission) << " 字节" << endl;
​
    return 0;
}

19.4 类成员指针

复制代码
// member_pointer.cpp -- 类成员指针
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <functional>
​
class Screen
{
public:
    using Action = Screen& (Screen::*)();   // 成员函数指针类型别名
​
    Screen(int h, int w, char c)
        : height_(h), width_(w), contents_(h * w, c), cursor_(0) {}
​
    // 成员函数
    Screen& home()  { cursor_ = 0; return *this; }
    Screen& end()   { cursor_ = contents_.size() - 1; return *this; }
    Screen& forward()
    {
        if (cursor_ < contents_.size() - 1) ++cursor_;
        return *this;
    }
    Screen& back()
    {
        if (cursor_ > 0) --cursor_;
        return *this;
    }
​
    char get() const { return contents_[cursor_]; }
    int  pos() const { return cursor_; }
​
    // 数据成员
    int         height_, width_;
    std::string contents_;
    int         cursor_;
};
​
int main()
{
    using namespace std;
​
    Screen s(3, 5, 'X');
​
    // ===== 数据成员指针 =====
    // 声明:类型 类名::*指针名
    int Screen::*pHeight = &Screen::height_;
    int Screen::*pWidth  = &Screen::width_;
​
    // 通过对象使用成员指针
    cout << "height = " << s.*pHeight << endl;   // 3
    cout << "width  = " << s.*pWidth  << endl;   // 5
​
    // 通过指针使用成员指针
    Screen* ps = &s;
    cout << "height = " << ps->*pHeight << endl;
​
    // ===== 成员函数指针 =====
    // 声明:返回类型 (类名::*指针名)(参数类型)
    Screen& (Screen::*pForward)() = &Screen::forward;
    Screen& (Screen::*pBack)()    = &Screen::back;
​
    // 通过对象调用
    (s.*pForward)();
    cout << "前进后位置:" << s.pos() << endl;
​
    (s.*pBack)();
    cout << "后退后位置:" << s.pos() << endl;
​
    // 通过指针调用
    (ps->*pForward)();
    cout << "通过指针前进:" << s.pos() << endl;
​
    // ===== 成员函数指针数组 =====
    Screen::Action actions[] = {
        &Screen::home,
        &Screen::forward,
        &Screen::end,
        &Screen::back
    };
​
    // 执行所有动作
    for (auto action : actions)
        (s.*action)();
​
    // ===== 使用 std::mem_fn 和 std::bind =====
    cout << "\n===== mem_fn 和 bind =====" << endl;
​
    // mem_fn:将成员函数包装为可调用对象
    auto getPos = mem_fn(&Screen::pos);
    cout << "pos = " << getPos(s) << endl;
​
    // bind:绑定成员函数
    auto forward = bind(&Screen::forward, &s);
    forward();
    cout << "bind forward后:" << s.pos() << endl;
​
    return 0;
}

19.5 嵌套类

复制代码
// nested_class.cpp -- 嵌套类
#include <iostream>
#include <string>
#include <memory>
​
// 嵌套类:定义在另一个类内部的类
class TextQuery
{
public:
    // 嵌套类:QueryResult
    class QueryResult
    {
        friend class TextQuery;
​
    public:
        QueryResult(const std::string& word, int count)
            : word_(word), count_(count) {}
​
        void print() const
        {
            std::cout << "\"" << word_ << "\" 出现 "
                      << count_ << " 次" << std::endl;
        }
​
        int count() const { return count_; }
​
    private:
        std::string word_;
        int         count_;
    };
​
    // TextQuery 的成员
    void addWord(const std::string& word)
    {
        wordCount_[word]++;
    }
​
    QueryResult query(const std::string& word) const
    {
        auto it = wordCount_.find(word);
        int count = (it != wordCount_.end()) ? it->second : 0;
        return QueryResult(word, count);
    }
​
private:
    std::map<std::string, int> wordCount_;
};
​
// 在类外定义嵌套类的成员
// TextQuery::QueryResult::QueryResult(...) { ... }
​
int main()
{
    using namespace std;
​
    TextQuery tq;
    string text = "the quick brown fox jumps over the lazy dog the";
​
    // 分词并统计
    istringstream iss(text);
    string word;
    while (iss >> word)
        tq.addWord(word);
​
    // 查询
    auto result1 = tq.query("the");
    auto result2 = tq.query("fox");
    auto result3 = tq.query("cat");
​
    result1.print();   // "the" 出现 3 次
    result2.print();   // "fox" 出现 1 次
    result3.print();   // "cat" 出现 0 次
​
    return 0;
}

19.6 union:一种节省空间的类

复制代码
// union_demo.cpp -- union
#include <iostream>
#include <string>
#include <new>
​
// ===== 基本 union =====
union Data
{
    int    ival;
    double dval;
    char   cval;
};   // 大小等于最大成员的大小
​
// ===== 匿名 union =====
struct Token
{
    enum class TokenKind { INT, DOUBLE, STRING };
    TokenKind kind;
​
    union   // 匿名union:成员直接在外层作用域可见
    {
        int    ival;
        double dval;
        // std::string sval;   // ⚠️ 含有构造函数的类型需要特殊处理
    };
};
​
// ===== 含有类类型成员的 union =====
class MyUnion
{
public:
    enum class Type { INT, STRING, NONE };
​
    MyUnion() : type_(Type::NONE) {}
​
    MyUnion(int v) : type_(Type::INT)
    {
        new (&ival_) int(v);   // 定位new
    }
​
    MyUnion(const std::string& s) : type_(Type::STRING)
    {
        new (&sval_) std::string(s);   // 定位new
    }
​
    MyUnion(const MyUnion& other) : type_(other.type_)
    {
        switch (type_)
        {
            case Type::INT:    new (&ival_) int(other.ival_); break;
            case Type::STRING: new (&sval_) std::string(other.sval_); break;
            default: break;
        }
    }
​
    ~MyUnion()
    {
        if (type_ == Type::STRING)
            sval_.~basic_string<char>();   // 手动析构
    }
​
    void show() const
    {
        switch (type_)
        {
            case Type::INT:    std::cout << "int: " << ival_ << std::endl; break;
            case Type::STRING: std::cout << "string: " << sval_ << std::endl; break;
            default: std::cout << "none" << std::endl;
        }
    }
​
private:
    Type type_;
    union
    {
        int         ival_;
        std::string sval_;
    };
};
​
int main()
{
    using namespace std;
​
    // 基本 union
    Data d;
    d.ival = 42;
    cout << "ival = " << d.ival << endl;
​
    d.dval = 3.14;   // 覆盖了 ival
    cout << "dval = " << d.dval << endl;
    // d.ival 现在是未定义的
​
    cout << "union大小:" << sizeof(Data) << " 字节" << endl;
​
    // 含类类型的 union
    MyUnion u1(42);
    MyUnion u2(string("Hello"));
    MyUnion u3;
​
    u1.show();
    u2.show();
    u3.show();
​
    return 0;
}

19.7 局部类

复制代码
// local_class.cpp -- 局部类
#include <iostream>
#include <string>
#include <functional>

// 局部类:定义在函数内部的类
std::function<int(int)> makeAdder(int n)
{
    // 局部类
    class Adder
    {
    public:
        Adder(int n) : n_(n) {}
        int operator()(int x) const { return x + n_; }

    private:
        int n_;
        // ⚠️ 局部类的限制:
        // 1. 不能定义静态数据成员
        // 2. 不能访问外层函数的局部变量(除非是静态的)
        // 3. 可以访问外层函数的类型名、静态变量、枚举值
    };

    return Adder(n);
}

// 局部类在模板中的应用
template <typename T>
std::function<bool(T)> makeGreaterThan(T threshold)
{
    class Comparator
    {
    public:
        Comparator(T t) : threshold_(t) {}
        bool operator()(T val) const { return val > threshold_; }

    private:
        T threshold_;
    };

    return Comparator(threshold);
}

int main()
{
    using namespace std;

    auto add5 = makeAdder(5);
    auto add10 = makeAdder(10);

    cout << "add5(3) = " << add5(3) << endl;    // 8
    cout << "add10(3) = " << add10(3) << endl;  // 13

    auto gt5 = makeGreaterThan(5);
    auto gt10 = makeGreaterThan(10.0);

    cout << boolalpha;
    cout << "7 > 5: " << gt5(7) << endl;    // true
    cout << "3 > 5: " << gt5(3) << endl;    // false
    cout << "15.0 > 10.0: " << gt10(15.0) << endl;  // true

    return 0;
}

19.8 固有的不可移植的特性

19.8.1 位域

复制代码
// bit_fields.cpp -- 位域
#include <iostream>

// 位域:允许将多个标志位打包到一个整数中
struct NetworkPacket
{
    unsigned int version   : 4;   // 4位:版本号(0-15)
    unsigned int type      : 4;   // 4位:类型(0-15)
    unsigned int flags     : 8;   // 8位:标志位
    unsigned int length    : 16;  // 16位:长度(0-65535)
    // 总共 32 位 = 4 字节
};

struct Permissions
{
    unsigned int read    : 1;   // 1位
    unsigned int write   : 1;   // 1位
    unsigned int execute : 1;   // 1位
    unsigned int         : 5;   // 5位填充(未命名)
};

int main()
{
    using namespace std;

    NetworkPacket pkt;
    pkt.version = 4;
    pkt.type    = 2;
    pkt.flags   = 0b00000001;
    pkt.length  = 1024;

    cout << "版本:" << pkt.version << endl;
    cout << "类型:" << pkt.type   << endl;
    cout << "标志:" << pkt.flags  << endl;
    cout << "长度:" << pkt.length << endl;
    cout << "结构体大小:" << sizeof(NetworkPacket) << " 字节" << endl;

    Permissions perm = {1, 1, 0};
    cout << "\n读权限:" << perm.read    << endl;
    cout << "写权限:" << perm.write   << endl;
    cout << "执行权限:" << perm.execute << endl;

    return 0;
}

19.8.2 volatile 限定符

复制代码
// volatile_demo.cpp -- volatile
#include <iostream>

// volatile:告诉编译器不要优化该变量
// 每次访问都从内存读取,不使用缓存

// 常见用途:
// 1. 硬件寄存器
// 2. 多线程共享变量(但不能替代互斥锁)
// 3. 信号处理程序中的变量

volatile int hardwareReg = 0;   // 模拟硬件寄存器

// volatile 与 const 组合
volatile const int readOnlyReg = 0xFF;   // 只读硬件寄存器

void readHardware()
{
    // 每次都从内存读取,不会被优化为只读一次
    for (int i = 0; i < 3; i++)
        std::cout << "寄存器值:" << hardwareReg << std::endl;
}

// volatile 成员函数
class HardwareDevice
{
public:
    void read() volatile
    {
        // 可以被 volatile 对象调用
        std::cout << "读取设备" << std::endl;
    }

    void write() volatile
    {
        std::cout << "写入设备" << std::endl;
    }
};

int main()
{
    readHardware();

    volatile HardwareDevice dev;
    dev.read();
    dev.write();

    return 0;
}

19.8.3 链接指示(extern "C")

复制代码
// extern_c.cpp -- 链接指示
#include <iostream>

// extern "C":告诉编译器使用C语言的链接规则
// 主要用于与C代码互操作

// 单个函数
extern "C" void c_function(int x)
{
    // 使用C链接,函数名不会被C++名字修饰
    std::cout << "C函数:" << x << std::endl;
}

// 多个函数
extern "C"
{
    void c_func1() { std::cout << "c_func1" << std::endl; }
    void c_func2() { std::cout << "c_func2" << std::endl; }
    int  c_add(int a, int b) { return a + b; }
}

// 包含C头文件
// extern "C"
// {
//     #include <stdio.h>
//     #include <string.h>
// }

// 在头文件中同时支持C和C++
#ifdef __cplusplus
extern "C" {
#endif

void shared_function(int x)
{
    std::cout << "共享函数:" << x << std::endl;
}

#ifdef __cplusplus
}
#endif

int main()
{
    c_function(42);
    c_func1();
    c_func2();
    std::cout << "c_add(3,4) = " << c_add(3, 4) << std::endl;
    shared_function(100);

    return 0;
}

19.9 综合示例:内存池

复制代码
// memory_pool.cpp -- 综合示例:内存池
#include <iostream>
#include <vector>
#include <string>
#include <stdexcept>
#include <new>
#include <cstring>

// 固定大小的内存池
template <typename T, size_t BlockSize = 64>
class MemoryPool
{
private:
    // 内存块
    struct Block
    {
        alignas(T) char data[sizeof(T)];
        bool inUse = false;
    };

    std::vector<Block> pool_;
    size_t             allocated_ = 0;

public:
    MemoryPool() : pool_(BlockSize) {}

    // 分配内存
    T* allocate()
    {
        for (auto& block : pool_)
        {
            if (!block.inUse)
            {
                block.inUse = true;
                ++allocated_;
                return reinterpret_cast<T*>(block.data);
            }
        }
        throw std::bad_alloc();
    }

    // 释放内存
    void deallocate(T* p) noexcept
    {
        for (auto& block : pool_)
        {
            if (reinterpret_cast<T*>(block.data) == p)
            {
                block.inUse = false;
                --allocated_;
                return;
            }
        }
    }

    // 构造对象
    template <typename... Args>
    T* construct(Args&&... args)
    {
        T* p = allocate();
        try
        {
            new (p) T(std::forward<Args>(args)...);   // 定位new
        }
        catch (...)
        {
            deallocate(p);
            throw;
        }
        return p;
    }

    // 析构并释放
    void destroy(T* p) noexcept
    {
        p->~T();
        deallocate(p);
    }

    size_t allocated() const { return allocated_; }
    size_t capacity()  const { return pool_.size(); }
    size_t available() const { return capacity() - allocated(); }
};

// 使用内存池的类
class Widget
{
public:
    Widget(const std::string& name, int val)
        : name_(name), val_(val)
    {
        std::cout << "[构造] " << name_ << "(" << val_ << ")" << std::endl;
    }

    ~Widget()
    {
        std::cout << "[析构] " << name_ << std::endl;
    }

    void show() const
    {
        std::cout << "Widget: " << name_ << " = " << val_ << std::endl;
    }

private:
    std::string name_;
    int         val_;
};

int main()
{
    using namespace std;

    MemoryPool<Widget, 5> pool;

    cout << "===== 内存池状态 =====" << endl;
    cout << "容量:" << pool.capacity() << endl;
    cout << "可用:" << pool.available() << endl;

    cout << "\n===== 分配对象 =====" << endl;
    Widget* w1 = pool.construct("Widget1", 100);
    Widget* w2 = pool.construct("Widget2", 200);
    Widget* w3 = pool.construct("Widget3", 300);

    cout << "已分配:" << pool.allocated() << endl;

    w1->show();
    w2->show();
    w3->show();

    cout << "\n===== 释放对象 =====" << endl;
    pool.destroy(w2);
    cout << "释放w2后,已分配:" << pool.allocated() << endl;

    cout << "\n===== 复用内存 =====" << endl;
    Widget* w4 = pool.construct("Widget4", 400);   // 复用w2的内存
    w4->show();

    cout << "\n===== 清理 =====" << endl;
    pool.destroy(w1);
    pool.destroy(w3);
    pool.destroy(w4);
    cout << "最终已分配:" << pool.allocated() << endl;

    return 0;
}

📝 第19章知识点总结

知识点 核心要点
重载 new/delete 类级别重载,operator new 分配内存,operator delete 释放
定位 new new (地址) 类型(参数),在指定内存构造,必须手动调用析构函数
dynamic_cast 安全向下转型,指针版本失败返回nullptr,引用版本失败抛bad_cast
typeid 返回 type_info,对多态类型返回动态类型,对指针返回静态类型
enum class 限定作用域,不隐式转换为int,可指定底层类型,推荐使用
数据成员指针 类型 类名::*ptr = &类名::成员,通过 .*->* 使用
成员函数指针 返回类型 (类名::*ptr)(参数),通过 .*->* 调用
mem_fn 将成员函数包装为可调用对象
嵌套类 定义在类内部,有自己的作用域,外层类不能直接访问嵌套类的私有成员
union 所有成员共享内存,大小等于最大成员,含类类型成员需手动管理
局部类 定义在函数内部,不能有静态数据成员,不能访问外层局部变量
位域 指定成员占用的位数,节省内存,常用于硬件协议
volatile 防止编译器优化,每次从内存读取,用于硬件寄存器和信号处理
extern "C" 使用C链接规则,用于C/C++互操作,防止名字修饰
相关推荐
玖釉-1 小时前
nvpro_core2 详解:NVIDIA Vulkan / OpenGL 图形样例背后的现代 C++ 基础库
c++·windows·图形渲染
不会C语言的男孩2 小时前
C++ Primer 第18章:用于大型程序的工具
开发语言·c++
星恒随风2 小时前
C++ 类和对象入门(三):拷贝构造、赋值运算符重载和深浅拷贝
开发语言·c++·笔记·学习
Cx330❀2 小时前
【MySQL基础】库与表的全面操纵指南
linux·服务器·网络·数据库·c++·mysql
凡人叶枫2 小时前
Effective C++ 条款03:尽可能使用 const
linux·开发语言·c++·嵌入式开发
hnjzsyjyj2 小时前
东方博宜OJ 1010:数组元素的排序 ← 桶排序
数据结构·排序算法·桶排序
小欣加油2 小时前
Leetcode31 下一个排列
数据结构·c++·算法·leetcode·职场和发展
凤凰院凶涛QAQ2 小时前
《Java版数据结构 & 集合类剖析》链表与LinkedList:节点手拉手,增删不用愁
java·数据结构·链表
Cx330❀2 小时前
【Linux网络】高性能 TCP 服务器:从多线程到线程池的架构演进与落地实践
linux·运维·服务器·网络·c++·tcp/ip·架构