C++开发必备之stl进阶(三高级操作)

C++ 标准模板库(STL)提供了强大的容器、迭代器和算法,能够帮助开发者编写高效、可重用的代码。在基础使用之上,STL 还提供了一些高级用法,使得我们可以编写出更灵活和高效的代码。以下是一些 STL 的高级使用技巧和方法。

1. STL 容器的自定义比较函数

在 STL 的有序容器中(如 std::setstd::map),可以通过自定义比较函数来定义容器的排序规则。

示例:自定义 std::set 的比较规则
#include <iostream>
#include <set>

// 自定义比较函数,按绝对值大小排序
struct Compare {
    bool operator()(int a, int b) const {
        return abs(a) < abs(b);
    }
};

int main() {
    std::set<int, Compare> s = { -3, 2, -1, 5, -4 };

    for (const auto& elem : s) {
        std::cout << elem << " ";  // 输出: -1 2 -3 -4 5
    }
    return 0;
}

2. Lambda 表达式与 STL 算法结合

C++11 引入了 Lambda 表达式,使得我们可以更加灵活地将自定义的逻辑嵌入到 STL 算法中,如 std::sortstd::find_if 等。

示例:使用 Lambda 表达式自定义排序
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 5, 3, 1, 4, 2 };

    // 按绝对值降序排序
    std::sort(vec.begin(), vec.end(), [](int a, int b) {
        return abs(a) > abs(b);
    });

    for (int i : vec) {
        std::cout << i << " ";  // 输出: 5 4 3 2 1
    }
    return 0;
}

示例:使用 Lambda 表达式查找特定元素

#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };

    // 查找第一个大于 3 的元素
    auto it = std::find_if(vec.begin(), vec.end(), [](int x) {
        return x > 3;
    });

    if (it != vec.end()) {
        std::cout << "First element greater than 3: " << *it << std::endl;  // 输出: 4
    }
    return 0;
}

3. 使用 std::transform 进行元素变换

std::transform 是 STL 中的一个强大算法,用于将一组元素转换为另一组元素。可以使用 Lambda 表达式或函数指针来定义转换规则。

示例:对容器中的每个元素进行平方
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };
    std::vector<int> result(vec.size());

    // 对每个元素平方
    std::transform(vec.begin(), vec.end(), result.begin(), [](int x) {
        return x * x;
    });

    for (int i : result) {
        std::cout << i << " ";  // 输出: 1 4 9 16 25
    }
    return 0;
}

4. 使用 std::accumulate 进行聚合操作

std::accumulate 是一个很有用的算法,用于对容器中的元素进行聚合操作,例如求和、求积或自定义聚合。

示例:使用 std::accumulate 求和
#include <iostream>
#include <vector>
#include <numeric>

int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };

    int sum = std::accumulate(vec.begin(), vec.end(), 0);
    std::cout << "Sum: " << sum << std::endl;  // 输出: 15

    return 0;
}

示例:使用 std::accumulate 进行字符串连接

#include <iostream>
#include <vector>
#include <numeric>
#include <string>

int main() {
    std::vector<std::string> words = { "Hello", "World", "!" };

    std::string sentence = std::accumulate(words.begin(), words.end(), std::string(""), 
                                           [](const std::string& a, const std::string& b) {
                                               return a + (a.length() > 0 ? " " : "") + b;
                                           });

    std::cout << "Sentence: " << sentence << std::endl;  // 输出: Hello World !
    return 0;
}

5. 使用 std::copystd::copy_if 进行容器拷贝

std::copy 用于将容器的元素拷贝到另一个容器,而 std::copy_if 则可以根据条件拷贝部分元素。

示例:使用 std::copy_if 复制符合条件的元素
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };
    std::vector<int> result;

    // 复制所有大于 3 的元素
    std::copy_if(vec.begin(), vec.end(), std::back_inserter(result), [](int x) {
        return x > 3;
    });

    for (int i : result) {
        std::cout << i << " ";  // 输出: 4 5
    }
    return 0;
}

6. 使用 std::partitionstd::stable_partition 进行容器分割

std::partition 可以将容器中的元素按某个条件进行分割,使得符合条件的元素排列在前,不符合条件的元素排列在后。

示例:将偶数和奇数分开
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 1, 2, 3, 4, 5 };

    // 将偶数放在前面,奇数放在后面
    std::partition(vec.begin(), vec.end(), [](int x) {
        return x % 2 == 0;
    });

    for (int i : vec) {
        std::cout << i << " ";  // 输出: 2 4 3 1 5 (偶数在前)
    }
    return 0;
}

7. 使用 std::unique 删除容器中的重复元素

std::unique 用于消除相邻的重复元素,常与 std::sort 结合使用以删除非相邻的重复元素。

示例:删除相邻的重复元素
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 1, 1, 2, 2, 3, 3, 4, 4 };

    auto it = std::unique(vec.begin(), vec.end());
    vec.erase(it, vec.end());

    for (int i : vec) {
        std::cout << i << " ";  // 输出: 1 2 3 4
    }
    return 0;
}

8. 使用 std::lower_boundstd::upper_bound 查找有序容器中的范围

  • std::lower_bound:返回第一个不小于给定值的元素的位置。
  • std::upper_bound:返回第一个大于给定值的元素的位置。
示例:查找有序数组中的范围
#include <iostream>
#include <vector>
#include <algorithm>

int main() {
    std::vector<int> vec = { 1, 2, 4, 4, 4, 5, 6 };

    auto lower = std::lower_bound(vec.begin(), vec.end(), 4);
    auto upper = std::upper_bound(vec.begin(), vec.end(), 4);

    std::cout << "Lower bound for 4: " << (lower - vec.begin()) << std::endl;  // 输出: 2
    std::cout << "Upper bound for 4: " << (upper - vec.begin()) << std::endl;  // 输出: 5

    return 0;
}

9. 智能指针与 STL 结合

STL 容器可以与智能指针很好地结合使用,从而避免手动管理内存。例如,使用 std::shared_ptrstd::unique_ptr 存储对象,容器会自动处理对象的生命周期。

示例:std::vector 中使用 std::shared_ptr
#include <iostream>
#include <memory>
#include <vector>

class Foo {
public:
    Foo(int value) : value_(value) {
        std::cout << "Constructing Foo(" << value_ << ")" << std::endl;
    }
    ~Foo() {
        std::cout << "Destructing Foo(" << value_ << ")" << std::endl;
    }

    int getValue() const { return value_; }

private:
    int value_;
};

int main() {
    std::vector<std::shared_ptr<Foo>> vec;

    vec.push_back(std::make_shared<Foo>(1));
    vec.push_back(std::make_shared<Foo>(2));
    vec.push_back(std::make_shared<Foo>(3));

    for (const auto& fooPtr : vec) {
        std::cout << "Foo value: " << fooPtr->getValue() << std::endl;
    }

    return 0;
}

在这个例子中,std::shared_ptr 自动管理了 Foo 对象的生命周期,容器销毁时对象也会被正确释放。

10. 高效的哈希容器

C++11 引入了 std::unordered_setstd::unordered_map,它们是基于哈希表的容器,提供了 O(1) 平均时间复杂度的查找、插入和删除操作。

示例:std::unordered_map 的使用
#include <iostream>
#include <unordered_map>
#include <string>

int main() {
    std::unordered_map<std::string, int> umap;

    umap["apple"] = 5;
    umap["banana"] = 2;
    umap["orange"] = 4;

    // 遍历 unordered_map
    for (const auto& pair : umap) {
        std::cout << pair.first << ": " << pair.second << std::endl;
    }

    // 查找元素
    if (umap.find("banana") != umap.end()) {
        std::cout << "Found banana, quantity: " << umap["banana"] << std::endl;
    }

    return 0;
}

11. 并行算法(C++17)

C++17 引入了并行 STL 算法,通过添加并行执行策略可以利用多核处理器并行执行算法。std::sort 等常见算法可以通过并行执行策略显著加速。

示例:并行 std::sort
#include <iostream>
#include <vector>
#include <algorithm>
#include <execution>  // C++17 并行执行策略

int main() {
    std::vector<int> vec = {5, 3, 1, 4, 2};

    // 使用并行执行策略排序
    std::sort(std::execution::par, vec.begin(), vec.end());

    for (int i : vec) {
        std::cout << i << " ";  // 输出: 1 2 3 4 5
    }

    return 0;
}

12. 使用 std::tuple 存储多种类型

std::tuple 是 C++11 引入的一种可以存储多个不同类型对象的容器,非常适合函数返回多个值或需要存储多种类型的数据。

示例:使用 std::tuple 返回多个值
#include <iostream>
#include <tuple>

std::tuple<int, double, std::string> getValues() {
    return std::make_tuple(42, 3.14, "Hello");
}

int main() {
    auto [i, d, s] = getValues();  // C++17 解构绑定

    std::cout << "Integer: " << i << ", Double: " << d << ", String: " << s << std::endl;
    return 0;
}

在这个例子中,std::tuple 用于返回多个不同类型的值,并通过 C++17 的结构化绑定直接解构返回值。

13. std::optional 处理可能不存在的值

C++17 引入了 std::optional,用于表示一个值可能存在或不存在。这在处理函数返回值或处理空值时非常有用。

示例:使用 std::optional
#include <iostream>
#include <optional>

std::optional<int> getValue(bool condition) {
    if (condition) {
        return 42;
    } else {
        return std::nullopt;  // 表示没有值
    }
}

int main() {
    auto value = getValue(true);
    if (value) {
        std::cout << "Value: " << *value << std::endl;
    } else {
        std::cout << "No value" << std::endl;
    }

    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值