编译运行:clang++ -std=c++26 -Wall -Wextra -pthread 测试_第26章_手写容器.cpp -o t && ./t(需先 cd 测试/)
// 第26章测试:手写 STL 组件
#include <print>
#include <memory>
#include <cstring>
#include <algorithm>
#include <ranges>
#include <type_traits>
int failures = 0;
#define CHECK(expr) \
do { \
if (!(expr)) { \
++failures; \
std::println("FAIL 第{}行: {}", __LINE__, #expr); \
} \
} while (0)
// 分配计数:验证构造/析构配对
struct Tracked {
static inline int alive = 0;
int v = 0;
explicit Tracked(int x = 0) : v(x) { ++alive; }
Tracked(const Tracked& o) : v(o.v) { ++alive; }
Tracked(Tracked&& o) noexcept : v(o.v) { ++alive; }
Tracked& operator=(const Tracked&) = default;
~Tracked() { --alive; }
};
// 26.2 MyVector
template <typename T>
class MyVector {
public:
MyVector() = default;
MyVector(const MyVector& o) { copy_from(o); }
MyVector(MyVector&& o) noexcept
: begin_(o.begin_), end_(o.end_), capacity_(o.capacity_) {
o.begin_ = o.end_ = o.capacity_ = nullptr;
}
MyVector& operator=(const MyVector& o) {
if (this != &o) { release(); copy_from(o); }
return *this;
}
MyVector& operator=(MyVector&& o) noexcept {
if (this != &o) {
release();
begin_ = o.begin_; end_ = o.end_; capacity_ = o.capacity_;
o.begin_ = o.end_ = o.capacity_ = nullptr;
}
return *this;
}
~MyVector() { release(); }
void push_back(const T& v) {
if (end_ == capacity_) grow();
new (end_) T(v);
++end_;
}
void push_back(T&& v) {
if (end_ == capacity_) grow();
new (end_) T(std::move(v));
++end_;
}
template <typename... Args>
void emplace_back(Args&&... args) {
if (end_ == capacity_) grow();
new (end_) T(std::forward<Args>(args)...);
++end_;
}
T& operator[](std::size_t i) { return begin_[i]; }
const T& operator[](std::size_t i) const { return begin_[i]; }
std::size_t size() const { return end_ - begin_; }
std::size_t capacity() const { return capacity_ - begin_; }
T* begin() { return begin_; }
T* end() { return end_; }
const T* begin() const { return begin_; }
const T* end() const { return end_; }
private:
void grow() {
std::size_t old_size = size(); // 先记旧 size!
std::size_t new_cap = capacity() == 0 ? 4 : capacity() * 2;
T* new_begin = reinterpret_cast<T*>(new char[new_cap * sizeof(T)]);
for (std::size_t i = 0; i < old_size; ++i)
new (new_begin + i) T(std::move(begin_[i])); // 移动元素
release_no_free(new_begin, new_begin + old_size); // 析构旧元素
delete[] reinterpret_cast<char*>(begin_);
begin_ = new_begin;
end_ = new_begin + old_size;
capacity_ = new_begin + new_cap;
}
void copy_from(const MyVector& o) {
if (o.size() == 0) return;
begin_ = reinterpret_cast<T*>(new char[o.size() * sizeof(T)]);
for (std::size_t i = 0; i < o.size(); ++i)
new (begin_ + i) T(o.begin_[i]);
end_ = begin_ + o.size();
capacity_ = end_;
}
void release_no_free(T*, T*) {
std::destroy(begin_, end_);
}
void release() {
std::destroy(begin_, end_);
delete[] reinterpret_cast<char*>(begin_);
begin_ = end_ = capacity_ = nullptr;
}
T* begin_ = nullptr;
T* end_ = nullptr;
T* capacity_ = nullptr;
};
// 26.3 MyUniquePtr
template <typename T>
class MyUniquePtr {
public:
MyUniquePtr() = default;
explicit MyUniquePtr(T* p) : ptr_(p) {}
~MyUniquePtr() { delete ptr_; }
MyUniquePtr(const MyUniquePtr&) = delete;
MyUniquePtr& operator=(const MyUniquePtr&) = delete;
MyUniquePtr(MyUniquePtr&& o) noexcept : ptr_(o.ptr_) { o.ptr_ = nullptr; }
MyUniquePtr& operator=(MyUniquePtr&& o) noexcept {
if (this != &o) { delete ptr_; ptr_ = o.ptr_; o.ptr_ = nullptr; }
return *this;
}
T& operator*() const { return *ptr_; }
T* operator->() const { return ptr_; }
T* get() const { return ptr_; }
explicit operator bool() const { return ptr_ != nullptr; }
T* release() { T* p = ptr_; ptr_ = nullptr; return p; }
void reset(T* p = nullptr) { delete ptr_; ptr_ = p; }
private:
T* ptr_ = nullptr;
};
// 26.4 MyString(简化版,无 SSO)
class MyString {
public:
MyString() = default;
MyString(const char* s) { assign(s); }
MyString(const MyString& o) { assign(o.c_str()); }
MyString(MyString&& o) noexcept : data_(o.data_), size_(o.size_) {
o.data_ = nullptr; o.size_ = 0;
}
MyString& operator=(const MyString& o) {
if (this != &o) assign(o.c_str());
return *this;
}
MyString& operator=(MyString&& o) noexcept {
if (this != &o) {
delete[] data_;
data_ = o.data_; size_ = o.size_;
o.data_ = nullptr; o.size_ = 0;
}
return *this;
}
~MyString() { delete[] data_; }
void assign(const char* s) {
delete[] data_;
size_ = std::strlen(s);
data_ = new char[size_ + 1];
std::memcpy(data_, s, size_ + 1);
}
const char* c_str() const { return data_ ? data_ : ""; }
std::size_t size() const { return size_; }
char operator[](std::size_t i) const { return data_[i]; }
private:
char* data_ = nullptr;
std::size_t size_ = 0;
};
int main() {
// ===== MyVector 基本功能 =====
{
MyVector<Tracked> v;
CHECK(v.size() == 0);
v.push_back(Tracked(1));
v.push_back(Tracked(2));
v.push_back(Tracked(3)); // 触发扩容(cap 4)
v.push_back(Tracked(4));
v.push_back(Tracked(5)); // 触发扩容(cap 8)
CHECK(v.size() == 5);
CHECK(v.capacity() >= 5);
CHECK(v[0].v == 1 && v[4].v == 5);
CHECK(Tracked::alive == 5); // 容器里恰好 5 个存活
// emplace_back
v.emplace_back(6);
CHECK(v.size() == 6 && v[5].v == 6);
} // 离开作用域全部析构
CHECK(Tracked::alive == 0); // 零泄漏!
// 拷贝与移动
{
MyVector<int> a;
for (int i = 0; i < 10; ++i) a.push_back(i);
MyVector<int> b = a; // 拷贝
CHECK(b.size() == 10 && b[9] == 9);
b[0] = 99;
CHECK(a[0] == 0); // 深拷贝独立
MyVector<int> c = std::move(a); // 移动
CHECK(c.size() == 10 && c[9] == 9);
}
// 迭代器 + 范围 for + 算法
{
MyVector<int> v;
for (int i = 0; i < 10; ++i) v.push_back(i * i);
int sum = 0;
for (int x : v) sum += x;
CHECK(sum == 285); // 0+1+4+...+81
std::ranges::sort(v); // 迭代器兼容 STL 算法
CHECK(std::ranges::is_sorted(v));
auto it = std::ranges::find(v, 25);
CHECK(it != v.end() && *it == 25);
}
// ===== MyUniquePtr =====
{
MyUniquePtr<Tracked> p(new Tracked(7));
CHECK(p.get() != nullptr);
CHECK((*p).v == 7);
CHECK(p->v == 7);
CHECK(static_cast<bool>(p));
Tracked* raw = p.release(); // 转移出去
CHECK(p.get() == nullptr);
delete raw; // 手动释放
CHECK(Tracked::alive == 0);
MyUniquePtr<Tracked> q(new Tracked(1));
MyUniquePtr<Tracked> r = std::move(q);
CHECK(q.get() == nullptr && r->v == 1);
r.reset(); // 立即释放
CHECK(Tracked::alive == 0);
}
// 编译期验证:不可拷贝
static_assert(!std::is_copy_constructible_v<MyUniquePtr<int>>);
static_assert(std::is_move_constructible_v<MyUniquePtr<int>>);
// ===== MyString =====
{
MyString s("hello");
CHECK(s.size() == 5);
CHECK(s[0] == 'h' && s[4] == 'o');
CHECK(std::strcmp(s.c_str(), "hello") == 0);
MyString copy = s; // 拷贝
CHECK(std::strcmp(copy.c_str(), "hello") == 0);
MyString moved = std::move(s); // 移动
CHECK(std::strcmp(moved.c_str(), "hello") == 0);
copy.assign("world");
CHECK(std::strcmp(copy.c_str(), "world") == 0);
}
if (failures == 0) std::println("全部通过");
return failures;
}