c++中常用的几个容器算法(accumulate equal fill copy replace erase sort bind)

accumulate

accumlate将第三个参数作为求和起点,这蕴含一个变成假定:该类型必须支持+操作,也就是定义了+运算符。

std::vector<char> v{'a','b','c','d'};
std::string sum=accumulate(v.cbegin(),v.cend(),string(""));//abcd

如果我们使用char作为第三个参数,那么会报错

std::string sum=accumulate(v.cbegin(),v.cend(),"");
//传递了一个字符串字面量,这个字面量的类型是const char*,它没有定义+运算符

equal

用于确定两个序列是否保存相同的值。它将第一个序列中的每个元素与第二个序列中的对应元素进行比较。equal不仅适用于顺序容器也能适用于关联容器,虽然关联容器中没有顺序,但是它依然能进行比较。

equal(list1.cbegin(),list1.cend(),list2.cbgin());

fill和fill_n

fill接受一对迭代器表示一个范围,同时还接受一个值作为第三个参数,将给定的这个值赋予输入序列中的每个元素。

vector<int> vec;
fill(vec.begin(),vec.end(),0);

fill_n接受一个迭代器指出一个单独的目的位置,从该序列指向的元素开始,填充指定个元素。函数fill_n写入指定个元素是不安全的,比如你不能向一个空的容器中写入多个元素。

vector<int> vec;
fill_n(vec.begin(),vec.size(),0);

fill_n(vec.begin(),10,0);//报错

copy

copy可以向一个目的位置迭代器指出的输出序列中的元素写入数据。

//数组也能算作一种容器,可以使用迭代器,和一些算法
int a1[]={0,1,2,3,4,5,6,7,8,9};
int a2[sizeof(a1)/sizeof(*a1)];
//返回一个指向a2尾元素后位置的迭代器
auto ret=copy(begin(a1),end(a1),a2);

replace和replace_copy

接受一个序列,并将器中所有等于给定值的元素都改为另一个值。此算法接受4个参数:前两个是一对迭代器,第三个是要搜索的值,第四个是新值。

replace(list.begin(),list.end(),0,42);

如果我们希望原序列不变可以使用replace_copy此算法接受第三个迭代器参数,指出调整后序列的保存位置:

replace_copy(list.cbegin(),list.cend(),back_inserter(ivec),0,42);

unique

unique可以使容器中的元素不重复,并返回一个指向不重复值范围末尾的迭代器,这一过程并未改变容器(改变容器大小,元素的值),仅仅使不重复的元素出现在序列开始部分,unique返回的迭代器指示向后的那些元素对用户是透明的。

原来的容器:|a|b|b|c|c|c|c|c|c|c|
修改之后的容器:|a|b|c|*|*|*|*|*|*|*|
                     ⬆返回的迭代器位置

erase

erase 方法用于从容器中移除元素。

std::vector<int> vec = {1, 2, 3, 4, 5};
vec.erase(vec.begin() + 2);//移除单个元素
vec.erase(vec.begin() + 1, vec.begin() + 3);//移除整个

sort

std::sort 是一个非常强大且常用的算法,它位于 头文件中。这个函数用于对容器中的元素进行排序,默认情况下按升序排列。它是基于快速排序、堆排序或其他高效排序算法的实现,具体取决于编译器和执行环境,确保具有很好的平均性能(通常是 𝑂(𝑛log𝑛)复杂度)。

  std::vector<int> v = {4, 1, 3, 9, 7};
  std::sort(v.begin(), v.end());

如果你需要按降序或根据自定义规则排序,可以提供一个比较函数或 lambda 表达式。

 std::sort(v.begin(), v.end(), [](int a, int b) { return a > b; });

bind

std::bind 是 cpp11 标准库中的一个函数适配器,它允许你将一个函数或函数对象与一些参数绑定在一起,从而创建一个新的可调用对象。这个新对象可以像普通函数一样被调用,但部分参数已经被固定。在成员函数的情况下,第一个参数通常是一个对象实例(通过指针或引用)。如果成员函数接受额外的参数,则这些参数将跟随对象实例参数。

#include <functional> // std::bind

auto boundFunc = std::bind(Callable, Arg1, Arg2, ...);

在 std::bind 中使用占位符 std::placeholders::_1, std::placeholders::_2, 等,来指定函数调用时的位置参数。未绑定的参数将在实际调用时传递。使用这一特性可以改变函数参数的位置,比如:

void func(int i,int j){
    ...
}
auto func2=bind(func,std::placeholders::_2,std::placeholders::_1);//相当于func的两个参数互换位置

std::bind 会将绑定的参数拷贝到内部存储中,这就意味着如果绑定的参数类型无法拷贝(例如,拷贝构造函数被删除的类),std::bind 将无法正常工作。在这种情况下,你需要使用 std::reference_wrapper 来处理这些特殊情况。

#include <iostream>
#include <functional> // std::bind, std::ref

class NonCopyable {
public:
    NonCopyable(int value) : value_(value) {}
    NonCopyable(const NonCopyable&) = delete; // 禁用拷贝构造函数
    void printValue() const {
        std::cout << "Value: " << value_ << std::endl;
    }
private:
    int value_;
};

int main() {
    NonCopyable obj(10);

    // 使用 std::ref 绑定 obj 的引用
    auto boundFunc = std::bind(&NonCopyable::printValue, std::ref(obj));
    
    // 调用绑定后的函数
    boundFunc(); // 输出: Value: 10

    return 0;
}

std::ref 是 cpp11 标准库中的一个工具函数,它用于创建一个 std::reference_wrapper 对象,以便在需要引用的情况下传递对象。std::reference_wrapper 是一个轻量级的封装类,它可以保存对一个对象的引用,而不是对象的副本。

std::reference_wrapper 是一个模板类,它用于封装对对象的引用,提供了与普通引用类似的接口:

#include <iostream>
#include <functional> // std::reference_wrapper

int main() {
    int a = 5;
    std::reference_wrapper<int> ref = std::ref(a);

    std::cout << "Original value: " << ref.get() << std::endl; // 输出: Original value: 5

    ref.get() = 10; // 修改引用的值

    std::cout << "Modified value: " << a << std::endl; // 输出: Modified value: 10

    return 0;
}

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值