C++编程:容器、工具与项目构建
立即解锁
发布时间: 2025-08-20 01:48:57 阅读量: 1 订阅数: 3 


懒惰程序员的C++入门指南
### C++ 编程:容器、工具与项目构建
#### 1. 容器操作与迭代器运用
在 C++ 编程中,容器操作和迭代器的使用是非常重要的部分。当遇到系统库报错信息时,要在错误信息里找到自己的文件名并着重关注。下面是一些相关的练习:
1. **反转列表函数**:用迭代器在 for 循环里编写一个 `reverse` 函数,返回所给列表的反转副本。
2. **迭代器版本反转函数**:不传递列表,而是传入其 `begin()` 和 `end()` 两个迭代器来实现反转。
3. **添加常量迭代器类**:给 `List` 类添加 `const_iterator` 类,同时需要新的 `begin` 和 `end` 的常量版本,使其返回 `const_iterator` 而非 `iterator`。
4. **融入反向迭代器**:结合之前让 `List` 能反向遍历的练习,把 `reverse_iterator` 和 `const_reverse_iterator` 融入 `List` 类。
5. **容器转换函数**:使用迭代器在 for 循环中编写函数,实现 STL 列表和向量之间的相互转换。
#### 2. 范围 for 循环与 auto 关键字
传统遍历容器的方式代码量较大,例如:
```cpp
for (vector<string>::const_iterator i = myVector.begin();
i != myVector.end();
++i)
cout << *i << ' ';
```
而范围 for 循环则简洁很多:
```cpp
vector<string> myVector; ...
for (const string& i : myVector)
cout << i << ' ';
```
这种方式同样适用于数组:
```cpp
int myArray[] = { 0, 1, 2, 3 };
for (int i : myArray)
cout << i << ' ';
```
若想更偷懒,可使用 `auto` 关键字让编译器确定元素类型:
```cpp
for (auto i : myArray)
cout << i << ' ';
for (auto i : myVector)
cout << i << ' ';
```
不过使用 `auto` 时要注意,若想修改数组元素,需使用引用:
```cpp
for (auto& i : myArray)
i *= 2;
```
若要避免不必要的复制,也可使用 `const auto&`:
```cpp
for (const auto& i : myVector)
cout << i << ' ';
```
#### 3. 初始化列表(可选)
从数组过渡到更复杂的容器时,会遗憾地失去方括号初始化列表。但我们也能在自己的类里使用 `{}` 列表,以下是 `Vector` 类的示例:
```cpp
#include <initializer_list>
template <typename T>
class Vector
{
public:
Vector (const std::initializer_list<T>& other);
...
};
template <typename T>
Vector<T>::Vector(const std::initializer_list<T>& other) : Vector ()
{
for (auto i = other.begin(); i != other.end(); ++i)
push_back(*i);
}
```
由于 `std::initializer_list` 内置了迭代器,也可用更简单的版本:
```cpp
template <typename T>
Vector<T>::Vector(const std::initializer_list<T>& other) : Vector ()
{
for (auto i : other)
push_back(i);
}
```
练习:因为 `std::initializer_list` 有 `begin()` 和 `end()`,但没有 `rbegin()` 和 `rend()`,若要用它初始化 `List`,`List` 需要有 `push_back` 方法。若还没创建,就创建 `List::push_back`,并给 `List` 一个接受初始化列表的构造函数。
#### 4. 算法库(可选)
`<algorithm>` 头文件包含很多对容器的操作。比如在名为 `digits` 的容器里查找元素:
```cpp
auto i = find(digits.begin(), digits.end(), 7);
if (i != digits.end())
cout << "Found a 7!\n";
```
`find` 函数会搜索从 `digits.begin()` 到 `digits.end()` 的范围,返回指向第一个等于 7 的元素的迭代器,若没有则返回 `digits.end()`。
复制容器内容到另一个容器:
```cpp
copy(digits.begin(), digits.end(), back_inserter(newContainer));
```
还能根据条件复制:
```cpp
bool isEven (int i) { return i % 2 == 0; }
...
copy_if(digits.begin(), digits.end(), back_inserter(evens), isEven);
```
大多数这些函数适用于任何容器类型。`sort(digits.begin(), digits.end());` 会对元素排序(元素需定义 `<` 运算符),但对列表排序要使用其成员函数 `myList.sort();`。
STL 容器没有重载 `<<` 或 `>>` 运算符用于输入输出,不过 STL 提供了另一种打印方式:
```cpp
copy(evens.begin(), evens.end(), ostream_iterator<int>(cout, " "));
```
这里需要包含 `<iterator>` 头文件。
#### 5. 擦除 - 移除惯用法
要从容器里移除不需要的元素,比如移除所有偶数:
```cpp
remove_if (digits.begin(), digits.end(), isEven);
```
但 `remove` 实际上并不移除元素,而是把不需要的元素移到序列末尾,返回新末尾的迭代器。所以要真正移除,需结合 `erase` 函数:
```cpp
erase (remove_if (digits.begin(), digits.end(), isEven),
digits.end());
```
#### 6. 避免容器操作中的错误
在 for 循环里添加或移除元素可能导致程序崩溃,因为改变容器内容会使已有迭代器失效。例如:
```cpp
for (auto i = digits.begin(); i != digits.end(); ++i)
if (isEven(*i))
digits.erase (i);
```
这里删除元素后,`i` 会指向不存在的元素,循环继续时程序就可能出错。可通过 `erase` 返回的迭代器来解决:
```cpp
for (auto i = digits.begin(); i != digits.end(); )
if (isEven(*i))
i = digits.erase (i);
else
+
```
0
0
复制全文
相关推荐










