Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
---

<!-- COVERAGE_START -->
![English Coverage](https://img.shields.io/badge/en_coverage-100%25-green.svg) 420/420 docs translated
![English Coverage](https://img.shields.io/badge/en_coverage-99%25-green.svg) 420/423 docs translated
<!-- COVERAGE_END -->

## 这是什么项目
Expand Down
78 changes: 78 additions & 0 deletions code/examples/vol34567/15_vector_deep_dive.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
// Standard: C++20
// vector 实现层深入:扩容追踪 / 迭代器失效 / move_if_noexcept / constexpr vector / erase_if
#include <iostream>
#include <vector>

// ---- move_if_noexcept 观察:move 构造故意不标 noexcept ----
class Tracked {
public:
int id;
static int move_count;
static int copy_count;

explicit Tracked(int i) : id(i) {}
Tracked(const Tracked& o) : id(o.id) { ++copy_count; }
Tracked(Tracked&& o) noexcept(false) : id(o.id) { ++move_count; }
};
int Tracked::move_count = 0;
int Tracked::copy_count = 0;

// ---- constexpr vector:编译期当临时工作区,只返回标量 ----
// transient allocation:常量求值期分配的内存必须在该求值内释放,
// 所以不能定义持久 constexpr vector 变量,只能让缓冲在函数内自然析构。
constexpr int sum_first_n(int n) {
std::vector<int> v;
for (int i = 0; i < n; ++i) {
v.push_back(i + 1);
}
int sum = 0;
for (int x : v) {
sum += x;
}
return sum;
}
static_assert(sum_first_n(100) == 5050); // 全程编译期完成

int main() {
std::cout << "== 扩容追踪(push_back 17 次)==\n";
std::vector<int> v;
for (int i = 0; i < 17; ++i) {
std::size_t cap_before = v.capacity();
v.push_back(i);
if (v.capacity() != cap_before) {
std::cout << "push " << i << ": capacity " << cap_before << " -> " << v.capacity()
<< '\n';
}
}

std::cout << "\n== 迭代器失效 ==\n";
std::vector<int> w{1, 2, 3};
w.reserve(3);
const int* p = &w[1];
w.push_back(4); // 余量足够,不扩容 → 指针仍有效
std::cout << "push_back 不扩容,指针有效? " << (p == &w[1]) << '\n';
w.reserve(100); // 超过 capacity → 换缓冲 → 指针失效
std::cout << "reserve 超容量后,指针有效? " << (p == &w[1]) << '\n';

std::cout << "\n== move_if_noexcept ==\n";
std::vector<Tracked> t;
t.reserve(2);
t.emplace_back(1);
t.emplace_back(2);
t.emplace_back(3); // 触发扩容
std::cout << "扩容时 moves=" << Tracked::move_count << " copies=" << Tracked::copy_count
<< "(noexcept(false) → 扩容倾向 copy;改成 noexcept 则变 move)\n";

std::cout << "\n== constexpr vector (C++20) ==\n";
std::cout << "sum_first_n(100) = " << sum_first_n(100) << "(编译期 static_assert 已验证)\n";

std::cout << "\n== erase_if (C++20) ==\n";
std::vector<int> e{1, 2, 3, 4, 5, 6};
std::size_t removed = std::erase_if(e, [](int x) { return x % 2 == 0; });
std::cout << "removed=" << removed << " left:";
for (int x : e) {
std::cout << ' ' << x;
}
std::cout << '\n';
return 0;
}
44 changes: 44 additions & 0 deletions code/examples/vol34567/16_string_memory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Standard: C++23
// string 内存深入:SSO 观察 + resize_and_overwrite 缓冲复用
#include <algorithm>
#include <cstring>
#include <iostream>
#include <string>

// 判断 string 的 data() 是否落在对象内联缓冲里(SSO 的标志)
bool points_inside_object(const std::string& s) {
const char* obj = reinterpret_cast<const char*>(&s);
return s.data() >= obj && s.data() < obj + sizeof(std::string);
}

// 模拟一个 C API:向 buf 最多写 n 字节,返回实际写入数
std::size_t fake_read(char* buf, std::size_t n) {
static const char msg[] = "hello";
std::size_t len = std::min(n, sizeof(msg) - 1);
std::memcpy(buf, msg, len);
return len;
}

int main() {
std::cout << "sizeof(std::string) = " << sizeof(std::string) << '\n';

std::string short_s = "hi"; // 很可能走 SSO
std::string long_s(64, 'x'); // 超过 SSO 阈值,出堆
std::cout << "short_s.data() 在对象内? " << points_inside_object(short_s) << "(SSO)\n";
std::cout << "long_s.data() 在对象内? " << points_inside_object(long_s) << "(出堆)\n";

std::cout << "\n== resize() 旧写法:先把 64 字符全部值初始化(清零),再截断 ==\n";
std::string old_buf;
old_buf.resize(64);
std::size_t got = fake_read(old_buf.data(), old_buf.size());
old_buf.resize(got);
std::cout << "old: '" << old_buf << "' (len=" << old_buf.size() << ")\n";

std::cout << "\n== resize_and_overwrite (C++23):不清零多余字符,回调报告实际长度 ==\n";
std::string buf;
buf.resize_and_overwrite(64, [](char* p, std::size_t n) noexcept {
return fake_read(p, n); // 只写实际字节,返回新长度(r ∈ [0, n])
});
std::cout << "new: '" << buf << "' (len=" << buf.size() << ")\n";
return 0;
}
33 changes: 33 additions & 0 deletions code/examples/vol34567/17_char8_t.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Standard: C++20
// char8_t 两坑(用注释封印,取消注释即编译失败)+ 两种正确写法
#include <iostream>
#include <string>

// 坑一:u8"" 在 C++20 起类型变为 const char8_t[],不再隐式转 const char*
// const char* p = u8"text"; // ill-formed since C++20

// 坑二:标准库显式 =delete 了 char8_t / const char8_t* 的 ostream 插入重载
// std::cout << u8"text"; // ill-formed since C++20
// std::cout << u8'z'; // ill-formed since C++20

// 正确写法之一:显式逐字节转换(内容不变,仅切换指针类型视角)
void print_as_char(const char* s) {
std::cout << s << '\n';
}

// 正确写法之二:用 std::u8string 类型安全地持有 UTF-8,并自定义打印
std::ostream& operator<<(std::ostream& os, const std::u8string& s) {
return os << reinterpret_cast<const char*>(s.data());
}

int main() {
// 路线 A:把 u8 字面量当 const char* 用(适合喂给只认窄字符的旧接口)
print_as_char(reinterpret_cast<const char*>(u8"text"));

// 路线 B:u8string 全程保持 UTF-8 类型,打印时再转
std::u8string u8s = u8"UTF-8 text";
std::cout << u8s << '\n';

std::cout << "__cpp_char8_t = " << __cpp_char8_t << '\n';
return 0;
}
Loading
Loading