第31章 自定义和扩展标准库

标准库的设计原则

C++标准库的设计遵循以下原则:

  1. 可扩展性:标准库设计为可扩展的,允许用户自定义和扩展其功能
  2. 泛型编程:使用模板实现泛型,提高代码重用性
  3. 迭代器范围:使用半开区间 [begin, end) 作为标准接口
  4. 策略模式:通过模板参数允许用户自定义行为
  5. 命名约定:遵循一致的命名约定,如小写字母加下划线
  6. 异常安全:提供不同级别的异常安全性

扩展标准库容器

自定义容器

创建符合标准库风格的自定义容器,需要实现以下接口:

  1. 迭代器:提供 begin()end() 方法,返回迭代器
  2. 容量管理:提供 size(), empty() 等方法
  3. 元素访问:提供 operator[], at() 等方法
  4. 修改操作:提供 insert(), erase(), clear() 等方法
  5. 分配器支持:支持自定义分配器

示例:自定义栈容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
template<typename T, typename Allocator = std::allocator<T>>
class Stack {
public:
using value_type = T;
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = const value_type&;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;

// 构造函数
Stack() = default;
explicit Stack(const Allocator& alloc) : data(alloc) {}

// 容量操作
bool empty() const noexcept {
return data.empty();
}

size_type size() const noexcept {
return data.size();
}

// 元素访问
reference top() {
if (empty()) {
throw std::out_of_range("Stack is empty");
}
return data.back();
}

const_reference top() const {
if (empty()) {
throw std::out_of_range("Stack is empty");
}
return data.back();
}

// 修改操作
void push(const value_type& value) {
data.push_back(value);
}

void push(value_type&& value) {
data.push_back(std::move(value));
}

template<typename... Args>
void emplace(Args&&... args) {
data.emplace_back(std::forward<Args>(args)...);
}

void pop() {
if (empty()) {
throw std::out_of_range("Stack is empty");
}
data.pop_back();
}

void swap(Stack& other) noexcept {
data.swap(other.data);
}

private:
std::vector<T, Allocator> data;
};

// 特化 std::swap
template<typename T, typename Allocator>
void swap(Stack<T, Allocator>& lhs, Stack<T, Allocator>& rhs) noexcept {
lhs.swap(rhs);
}

扩展现有容器

通过继承或组合扩展现有容器:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 通过组合扩展 std::vector
template<typename T>
class ExtendedVector {
public:
// 暴露 std::vector 的接口
void push_back(const T& value) {
data.push_back(value);
}

void push_back(T&& value) {
data.push_back(std::move(value));
}

// 添加新功能
void push_front(const T& value) {
data.insert(data.begin(), value);
}

void push_front(T&& value) {
data.insert(data.begin(), std::move(value));
}

// 其他方法...

private:
std::vector<T> data;
};

自定义迭代器

迭代器的概念

C++标准库定义了五种迭代器类别:

  1. 输入迭代器:只读,单向移动
  2. 输出迭代器:只写,单向移动
  3. 前向迭代器:可读写,单向移动,可重复遍历
  4. 双向迭代器:可读写,双向移动
  5. 随机访问迭代器:可读写,随机访问

实现自定义迭代器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
template<typename T>
class Node {
public:
T value;
Node* next;

Node(const T& val) : value(val), next(nullptr) {}
};

template<typename T>
class LinkedList {
public:
class Iterator {
public:
using iterator_category = std::forward_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&

Iterator(Node<T>* node) : current(node) {}

reference operator*() const {
return current->value;
}

pointer operator->() const {
return &current->value;
}

Iterator& operator++() {
current = current->next;
return *this;
}

Iterator operator++(int) {
Iterator temp = *this;
current = current->next;
return temp;
}

bool operator==(const Iterator& other) const {
return current == other.current;
}

bool operator!=(const Iterator& other) const {
return current != other.current;
}

private:
Node<T>* current;
};

LinkedList() : head(nullptr), tail(nullptr) {}

void push_back(const T& value) {
Node<T>* newNode = new Node<T>(value);
if (!head) {
head = tail = newNode;
} else {
tail->next = newNode;
tail = newNode;
}
}

Iterator begin() const {
return Iterator(head);
}

Iterator end() const {
return Iterator(nullptr);
}

private:
Node<T>* head;
Node<T>* tail;
};

// 使用示例
int main() {
LinkedList<int> list;
list.push_back(1);
list.push_back(2);
list.push_back(3);

for (int value : list) {
std::cout << value << " "; // 输出: 1 2 3
}
std::cout << std::endl;

return 0;
}

扩展标准库算法

自定义算法

创建符合标准库风格的自定义算法,需要遵循以下原则:

  1. 使用迭代器范围:接受 [begin, end) 迭代器范围
  2. 模板化:使用模板参数支持不同类型
  3. 命名约定:遵循标准库命名约定
  4. 异常安全:提供适当的异常安全性

示例:自定义算法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 查找最大值和最小值
template<typename ForwardIt>
auto minmax_element(ForwardIt first, ForwardIt last) {
using value_type = typename std::iterator_traits<ForwardIt>::value_type;

if (first == last) {
return std::make_pair(last, last);
}

ForwardIt min_it = first;
ForwardIt max_it = first;
++first;

for (; first != last; ++first) {
if (*first < *min_it) {
min_it = first;
} else if (*first > *max_it) {
max_it = first;
}
}

return std::make_pair(min_it, max_it);
}

// 使用示例
int main() {
std::vector<int> v = {3, 1, 4, 1, 5, 9, 2, 6};
auto [min_it, max_it] = minmax_element(v.begin(), v.end());

std::cout << "Min: " << *min_it << ", Max: " << *max_it << std::endl;

return 0;
}

算法适配器

创建算法适配器,扩展现有算法的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 带谓词的 for_each 算法
template<typename InputIt, typename UnaryFunction>
UnaryFunction for_each_if(InputIt first, InputIt last, UnaryFunction f,
std::function<bool(const typename std::iterator_traits<InputIt>::value_type&)> pred) {
for (; first != last; ++first) {
if (pred(*first)) {
f(*first);
}
}
return f;
}

// 使用示例
int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 打印偶数
for_each_if(v.begin(), v.end(),
[](int n) { std::cout << n << " "; },
[](int n) { return n % 2 == 0; });
std::cout << std::endl;

return 0;
}

自定义分配器

分配器的概念

分配器是标准库中用于内存管理的组件,它提供以下功能:

  1. 内存分配:分配原始内存
  2. 内存释放:释放分配的内存
  3. 对象构造:在分配的内存中构造对象
  4. 对象析构:析构对象但不释放内存

实现自定义分配器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
template<typename T>
class CustomAllocator {
public:
using value_type = T;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
using propagate_on_container_move_assignment = std::true_type;

// 默认构造函数
CustomAllocator() noexcept = default;

// 拷贝构造函数
template<typename U>
CustomAllocator(const CustomAllocator<U>&) noexcept {}

// 分配内存
T* allocate(size_type n) {
if (n > max_size()) {
throw std::bad_alloc();
}
return static_cast<T*>(std::malloc(n * sizeof(T)));
}

// 释放内存
void deallocate(T* p, size_type) noexcept {
std::free(p);
}

// 最大分配大小
size_type max_size() const noexcept {
return std::numeric_limits<size_type>::max() / sizeof(T);
}

// 构造对象
template<typename U, typename... Args>
void construct(U* p, Args&&... args) {
::new (static_cast<void*>(p)) U(std::forward<Args>(args)...);
}

// 析构对象
template<typename U>
void destroy(U* p) {
p->~U();
}
};

// 比较运算符
template<typename T, typename U>
bool operator==(const CustomAllocator<T>&, const CustomAllocator<U>&) noexcept {
return true;
}

template<typename T, typename U>
bool operator!=(const CustomAllocator<T>&, const CustomAllocator<U>&) noexcept {
return false;
}

// 使用示例
int main() {
std::vector<int, CustomAllocator<int>> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);

for (int i : v) {
std::cout << i << " ";
}
std::cout << std::endl;

return 0;
}

扩展标准库流

自定义流缓冲区

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
class CustomStreambuf : public std::streambuf {
private:
std::vector<char> buffer;
static constexpr std::size_t buffer_size = 256;

public:
CustomStreambuf() {
buffer.resize(buffer_size);
setp(buffer.data(), buffer.data() + buffer.size() - 1);
}

protected:
// 缓冲区满时调用
int_type overflow(int_type c) override {
if (c != traits_type::eof()) {
// 确保缓冲区有空间
*pptr() = static_cast<char>(c);
pbump(1);

// 刷新缓冲区
if (sync() == -1) {
return traits_type::eof();
}
}
return c;
}

// 刷新缓冲区
int sync() override {
if (pbase() != pptr()) {
// 处理缓冲区中的数据
std::cout.write(pbase(), pptr() - pbase());
std::cout.flush();

// 重置缓冲区
setp(buffer.data(), buffer.data() + buffer.size() - 1);
}
return 0;
}
};

// 自定义输出流
class CustomOutputStream : public std::ostream {
private:
CustomStreambuf streambuf;

public:
CustomOutputStream() : std::ostream(&streambuf) {}
};

// 使用示例
int main() {
CustomOutputStream out;
out << "Hello, Custom Stream!" << std::endl;

return 0;
}

自定义流操纵符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// 自定义流操纵符
std::ostream& hexify(std::ostream& os) {
return os << std::hex << std::showbase;
}

std::ostream& resetify(std::ostream& os) {
return os << std::dec << std::noshowbase;
}

// 使用示例
int main() {
int value = 255;
std::cout << "Decimal: " << value << std::endl;
std::cout << "Hex: " << hexify << value << resetify << std::endl;

return 0;
}

自定义函子和函数对象

标准库中的函数对象

标准库提供了多种函数对象,如:

  1. 算术运算std::plus, std::minus, std::multiplies
  2. 比较运算std::equal_to, std::greater, std::less
  3. 逻辑运算std::logical_and, std::logical_or, std::logical_not
  4. 函数适配器std::bind, std::mem_fn

自定义函数对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// 自定义谓词
struct IsEven {
bool operator()(int n) const {
return n % 2 == 0;
}
};

// 自定义转换器
struct Square {
template<typename T>
T operator()(T value) const {
return value * value;
}
};

// 使用示例
int main() {
std::vector<int> v = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

// 使用自定义谓词
auto count = std::count_if(v.begin(), v.end(), IsEven());
std::cout << "Even numbers: " << count << std::endl;

// 使用自定义转换器
std::vector<int> squared(v.size());
std::transform(v.begin(), v.end(), squared.begin(), Square());

std::cout << "Squared: ";
for (int n : squared) {
std::cout << n << " ";
}
std::cout << std::endl;

return 0;
}

扩展标准库的策略模式

策略模式的应用

标准库中广泛使用策略模式,如:

  1. 排序算法std::sort 允许自定义比较策略
  2. 容器std::set 允许自定义排序策略
  3. 分配器:所有容器都允许自定义分配策略
  4. 哈希表std::unordered_map 允许自定义哈希策略

示例:自定义哈希策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// 自定义哈希函数
struct StringHash {
std::size_t operator()(const std::string& s) const {
std::size_t hash = 0;
for (char c : s) {
hash = hash * 31 + static_cast<unsigned char>(c);
}
return hash;
}
};

// 自定义相等性比较
struct StringEqual {
bool operator()(const std::string& lhs, const std::string& rhs) const {
return lhs == rhs;
}
};

// 使用自定义哈希表
using CustomHashMap = std::unordered_map<std::string, int, StringHash, StringEqual>;

// 使用示例
int main() {
CustomHashMap map;
map["one"] = 1;
map["two"] = 2;
map["three"] = 3;

for (const auto& pair : map) {
std::cout << pair.first << ": " << pair.second << std::endl;
}

return 0;
}

自定义类型特征

类型特征的概念

类型特征(Type Traits)是标准库中用于编译时类型信息查询和转换的工具,定义在 <type_traits> 头文件中。

实现自定义类型特征

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 自定义类型特征:检查类型是否为指针
template<typename T>
struct is_pointer {
static constexpr bool value = false;
};

template<typename T>
struct is_pointer<T*> {
static constexpr bool value = true;
};

// 辅助变量模板
template<typename T>
inline constexpr bool is_pointer_v = is_pointer<T>::value;

// 使用示例
int main() {
std::cout << "is_pointer<int>: " << is_pointer_v<int> << std::endl;
std::cout << "is_pointer<int*>: " << is_pointer_v<int*> << std::endl;

return 0;
}

类型特征的应用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 根据类型特征选择不同的实现
template<typename T>
void process_impl(const T& value, std::true_type) {
std::cout << "Processing pointer: " << *value << std::endl;
}

template<typename T>
void process_impl(const T& value, std::false_type) {
std::cout << "Processing value: " << value << std::endl;
}

template<typename T>
void process(const T& value) {
process_impl(value, std::is_pointer<T>{});
}

// 使用示例
int main() {
int x = 42;
int* px = &x;

process(x); // 处理值
process(px); // 处理指针

return 0;
}

扩展标准库的最佳实践

1. 遵循标准库风格

  • 使用与标准库一致的命名约定
  • 遵循标准库的接口设计,如迭代器范围
  • 使用与标准库一致的异常处理策略
  • 提供与标准库一致的文档

2. 测试与标准库兼容性

  • 确保自定义组件与标准库算法兼容
  • 测试不同类型的输入和边界情况
  • 确保异常安全性符合预期

3. 性能考虑

  • 优化自定义组件的性能,与标准库组件相当
  • 避免不必要的内存分配和拷贝
  • 考虑缓存局部性

4. 可维护性

  • 保持代码简洁明了
  • 添加适当的注释和文档
  • 遵循良好的代码组织

5. 避免修改标准库

  • 不要修改标准库的头文件或实现
  • 不要依赖标准库的内部实现细节
  • 使用继承或组合扩展标准库功能

示例:完整的自定义容器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
// 自定义环形缓冲区容器
template<typename T, typename Allocator = std::allocator<T>>
class CircularBuffer {
public:
using value_type = T;
using allocator_type = Allocator;
using reference = value_type&;
using const_reference = const value_type&;
using pointer = typename std::allocator_traits<Allocator>::pointer;
using const_pointer = typename std::allocator_traits<Allocator>::const_pointer;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;

// 迭代器
class Iterator {
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&

Iterator(CircularBuffer* buffer, size_type index)
: buffer(buffer), index(index) {}

reference operator*() const {
return buffer->data[(buffer->start + index) % buffer->capacity_];
}

pointer operator->() const {
return &buffer->data[(buffer->start + index) % buffer->capacity_];
}

reference operator[](difference_type n) const {
return buffer->data[(buffer->start + index + n) % buffer->capacity_];
}

Iterator& operator++() {
++index;
return *this;
}

Iterator operator++(int) {
Iterator temp = *this;
++index;
return temp;
}

Iterator& operator--() {
--index;
return *this;
}

Iterator operator--(int) {
Iterator temp = *this;
--index;
return temp;
}

Iterator& operator+=(difference_type n) {
index += n;
return *this;
}

Iterator operator+(difference_type n) const {
Iterator temp = *this;
return temp += n;
}

Iterator& operator-=(difference_type n) {
index -= n;
return *this;
}

Iterator operator-(difference_type n) const {
Iterator temp = *this;
return temp -= n;
}

difference_type operator-(const Iterator& other) const {
return index - other.index;
}

bool operator==(const Iterator& other) const {
return buffer == other.buffer && index == other.index;
}

bool operator!=(const Iterator& other) const {
return !(*this == other);
}

bool operator<(const Iterator& other) const {
return index < other.index;
}

bool operator<=(const Iterator& other) const {
return index <= other.index;
}

bool operator>(const Iterator& other) const {
return index > other.index;
}

bool operator>=(const Iterator& other) const {
return index >= other.index;
}

private:
CircularBuffer* buffer;
size_type index;
};

using iterator = Iterator;
using const_iterator = Iterator; // 简化实现,实际应该实现 const 版本
using reverse_iterator = std::reverse_iterator<iterator>;
using const_reverse_iterator = std::reverse_iterator<const_iterator>;

// 构造函数
explicit CircularBuffer(size_type capacity = 16, const Allocator& alloc = Allocator())
: allocator(alloc), capacity_(capacity), size_(0), start(0), end(0) {
data = std::allocator_traits<Allocator>::allocate(allocator, capacity_);
}

// 析构函数
~CircularBuffer() {
// 析构元素
for (size_type i = 0; i < size_; ++i) {
std::allocator_traits<Allocator>::destroy(allocator,
&data[(start + i) % capacity_]);
}
// 释放内存
std::allocator_traits<Allocator>::deallocate(allocator, data, capacity_);
}

// 容量操作
bool empty() const noexcept {
return size_ == 0;
}

size_type size() const noexcept {
return size_;
}

size_type capacity() const noexcept {
return capacity_;
}

void reserve(size_type new_capacity) {
if (new_capacity <= capacity_) {
return;
}

// 分配新内存
pointer new_data = std::allocator_traits<Allocator>::allocate(allocator, new_capacity);

// 复制元素
for (size_type i = 0; i < size_; ++i) {
std::allocator_traits<Allocator>::construct(allocator,
&new_data[i], std::move(data[(start + i) % capacity_]));
std::allocator_traits<Allocator>::destroy(allocator,
&data[(start + i) % capacity_]);
}

// 释放旧内存
std::allocator_traits<Allocator>::deallocate(allocator, data, capacity_);

// 更新状态
data = new_data;
capacity_ = new_capacity;
start = 0;
end = size_;
}

// 元素访问
reference front() {
if (empty()) {
throw std::out_of_range("CircularBuffer is empty");
}
return data[start];
}

const_reference front() const {
if (empty()) {
throw std::out_of_range("CircularBuffer is empty");
}
return data[start];
}

reference back() {
if (empty()) {
throw std::out_of_range("CircularBuffer is empty");
}
return data[(end - 1) % capacity_];
}

const_reference back() const {
if (empty()) {
throw std::out_of_range("CircularBuffer is empty");
}
return data[(end - 1) % capacity_];
}

reference operator[](size_type n) {
if (n >= size_) {
throw std::out_of_range("Index out of range");
}
return data[(start + n) % capacity_];
}

const_reference operator[](size_type n) const {
if (n >= size_) {
throw std::out_of_range("Index out of range");
}
return data[(start + n) % capacity_];
}

reference at(size_type n) {
return operator[](n);
}

const_reference at(size_type n) const {
return operator[](n);
}

// 迭代器
iterator begin() noexcept {
return iterator(this, 0);
}

const_iterator begin() const noexcept {
return const_iterator(const_cast<CircularBuffer*>(this), 0);
}

iterator end() noexcept {
return iterator(this, size_);
}

const_iterator end() const noexcept {
return const_iterator(const_cast<CircularBuffer*>(this), size_);
}

reverse_iterator rbegin() noexcept {
return reverse_iterator(end());
}

const_reverse_iterator rbegin() const noexcept {
return const_reverse_iterator(end());
}

reverse_iterator rend() noexcept {
return reverse_iterator(begin());
}

const_reverse_iterator rend() const noexcept {
return const_reverse_iterator(begin());
}

// 修改操作
void push_back(const value_type& value) {
if (size_ == capacity_) {
reserve(capacity_ * 2);
}

std::allocator_traits<Allocator>::construct(allocator, &data[end], value);
end = (end + 1) % capacity_;
++size_;
}

void push_back(value_type&& value) {
if (size_ == capacity_) {
reserve(capacity_ * 2);
}

std::allocator_traits<Allocator>::construct(allocator, &data[end], std::move(value));
end = (end + 1) % capacity_;
++size_;
}

template<typename... Args>
void emplace_back(Args&&... args) {
if (size_ == capacity_) {
reserve(capacity_ * 2);
}

std::allocator_traits<Allocator>::construct(allocator, &data[end], std::forward<Args>(args)...);
end = (end + 1) % capacity_;
++size_;
}

void pop_front() {
if (empty()) {
throw std::out_of_range("CircularBuffer is empty");
}

std::allocator_traits<Allocator>::destroy(allocator, &data[start]);
start = (start + 1) % capacity_;
--size_;
}

void clear() noexcept {
for (size_type i = 0; i < size_; ++i) {
std::allocator_traits<Allocator>::destroy(allocator,
&data[(start + i) % capacity_]);
}

size_ = 0;
start = 0;
end = 0;
}

private:
Allocator allocator;
pointer data;
size_type capacity_;
size_type size_;
size_type start;
size_type end;
};

// 使用示例
int main() {
CircularBuffer<int> buf(5);

// 添加元素
for (int i = 1; i <= 10; ++i) {
buf.push_back(i);
}

// 遍历元素
std::cout << "Elements: ";
for (int n : buf) {
std::cout << n << " ";
}
std::cout << std::endl;

// 访问元素
std::cout << "Front: " << buf.front() << std::endl;
std::cout << "Back: " << buf.back() << std::endl;
std::cout << "Element at 2: " << buf[2] << std::endl;

// 删除元素
buf.pop_front();
std::cout << "After pop_front: ";
for (int n : buf) {
std::cout << n << " ";
}
std::cout << std::endl;

return 0;
}

总结

自定义和扩展标准库是C++编程中的重要技能,它允许我们:

  1. 扩展标准库功能:为标准库添加新的功能和组件
  2. 自定义行为:根据特定需求自定义标准库的行为
  3. 提高代码重用性:创建可重用的组件,遵循标准库的设计原则
  4. 优化性能:为特定场景创建高性能的实现

在自定义和扩展标准库时,应该遵循标准库的设计原则,确保与标准库的兼容性,同时考虑性能和可维护性。通过合理地自定义和扩展标准库,我们可以创建更加灵活、高效、可维护的C++代码。