测试_第08章_指针与内存.cpp

← 测试总览 · 目录

编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第08章_指针与内存.cpp -o t && ./t(需先 cd 测试/

// 第8章测试:指针与内存(智能指针 / RAII / 引用)
#include <print>
#include <memory>
#include <string>
#include <vector>

int failures = 0;
#define CHECK(expr)                                                         \
    do {                                                                    \
        if (!(expr)) {                                                      \
            ++failures;                                                     \
            std::println("FAIL 第{}行: {}", __LINE__, #expr);              \
        }                                                                   \
    } while (0)

struct Counter {
    static inline int alive = 0;                        // C++17 inline 变量
    Counter() { ++alive; }
    ~Counter() { --alive; }
};

// RAII 类演示:析构自动还资源
class ScopedGuard {
public:
    explicit ScopedGuard(const std::string& name) : name_(name) {
        std::println("进入作用域:{}", name_);
        ++active_;
    }
    ~ScopedGuard() {
        std::println("离开作用域:{}", name_);
        --active_;
    }
    static inline int active_ = 0;
private:
    std::string name_;
};

int main() {
    // 8.1 指针基础
    int x = 10;
    int* p = &x;
    *p = 20;
    CHECK(x == 20);
    CHECK(p != nullptr);
    int* np = nullptr;
    CHECK(np == nullptr);

    // 8.4 智能指针:unique_ptr
    std::unique_ptr<int> u = std::make_unique<int>(42);
    CHECK(*u == 42);
    std::unique_ptr<Counter> cu = std::make_unique<Counter>();
    CHECK(Counter::alive == 1);
    cu.reset();                                         // 手动释放
    CHECK(Counter::alive == 0);

    // 独占性验证
    std::unique_ptr<int> u2 = std::make_unique<int>(1);
    std::unique_ptr<int> u3 = std::move(u2);            // 所有权转移
    CHECK(u2 == nullptr);
    CHECK(*u3 == 1);

    // shared_ptr 引用计数
    std::shared_ptr<Counter> s1 = std::make_shared<Counter>();
    CHECK(s1.use_count() == 1);
    {
        std::shared_ptr<Counter> s2 = s1;
        CHECK(s1.use_count() == 2);
        CHECK(Counter::alive == 1);                     // 同一对象只构造一次
    }
    CHECK(s1.use_count() == 1);                         // s2 销毁,计数回 1
    s1.reset();
    CHECK(Counter::alive == 0);                         // 计数归零,真正释放

    // weak_ptr:不增加计数
    std::shared_ptr<int> sp = std::make_shared<int>(7);
    std::weak_ptr<int> wp = sp;
    CHECK(sp.use_count() == 1);                         // weak 不计数
    CHECK(wp.expired() == false);
    if (auto locked = wp.lock()) CHECK(*locked == 7);
    sp.reset();
    CHECK(wp.expired());                                // 对象没了

    // 循环引用演示(weak 破环):
    struct Node {
        std::string name;
        std::shared_ptr<Node> next;
        std::weak_ptr<Node> parent;                     // 用 weak 避免环
    };
    auto n1 = std::make_shared<Node>();
    auto n2 = std::make_shared<Node>();
    n1->next = n2;
    n2->parent = n1;                                    // weak 不形成环

    // 8.5 RAII:作用域结束自动析构
    CHECK(ScopedGuard::active_ == 0);
    {
        ScopedGuard g("测试块");
        CHECK(ScopedGuard::active_ == 1);
    }                                                   // 这里自动析构
    CHECK(ScopedGuard::active_ == 0);

    // 8.6 引用:不能为空、不能换绑
    int a = 1, b = 2;
    int& r = a;
    r = b;                                              // 赋值不是换绑!
    CHECK(a == 2 && b == 2);                            // a 被赋成 2,r 仍是 a 的别名
    CHECK(&r == &a);

    // 智能指针管理容器
    auto vec = std::make_unique<std::vector<int>>();
    vec->push_back(1);
    vec->push_back(2);
    CHECK(vec->size() == 2);

    if (failures == 0) std::println("全部通过");
    return failures;
}