C++之泛型算法

-
-
2026-06-05 16:29

一、标准库常用算法

  • 大多数算法定义在头文件algorithm中,标准库还在头文件numeric中定义了一组数值泛型算法。
  • 迭代器令算法不依赖于容器,但算法依赖于元素类型的操作。
  • 标准库算法对迭代器而不是容器进行操作,因此算法不能直接添加或删除元素,故永远不会改变底层容器的大小。
算法作用使用示例备注
find查找
auto result = find(v.cbegin(), v.cend(), target); /// 若未查找到target,将返回v.cend()

前两个参数表示要查找的范围的迭代器,第三个参数是要查找的目标值。

若找到匹配值,则返回第一个找到的匹配值,

若无匹配值,则返回第二个参数。

count查找给定值在序列中出现的次数
std::int64_t nNum = std::count(v.cbegin(),v.cend(), target);
 
accumulate求和
int nSum = accumulate(v.cbegin(), v.cend(), 0); /// 求v中全部元素的和
前两个参数表示要求和的元素的范围,第三个参数为和的初始值。
fill填充元素
fill(v.begin(), v.end(), 0); /// 将每个元素重置为0
 
fill_n填充元素
fill_n(v.begin(), v.size(), 0); /// 将所有元素重置为0
v中至少需要有第二个参数指定的元素个数,否则将发生越界。
back_inserter保证有足够元素空间来容纳输出数据
fill_n(back_inserter(v), 10, 0); /// 添加10个元素到vec末尾
这个例子中不需要保证v有10个元素空间,因为插入迭代器(即:back_inserter)会自动获取足够空间。
copy拷贝算法,向目的位置迭代器指向的输出序列中的元素写入数据
auto ret = copy(begin(a1), end(a1), a2); /// 把a1的内容拷贝给a2,需要确保a2的空间大于等于a1
返回的是目的位置迭代器递增后的值,本例中指向a2尾元素之后的位置。
replace替换指定值
replace(v.begin(), v.end(), 0, 42);
直接修改v中的元素
replace_copy
replace_copy(v.begin(), v.end(), back_inserter(vNew), 0, 42);
不修改v中的元素,将修改后的序列保存到vNew中。

二、向算法传递函数

谓词

  • 谓词是一个可用的表达式,其返回结果是一个能用作条件的值。标准库算法所使用的谓词分为两类:
    • 一元谓词:只接受单一参数
    • 二元谓词:接受两个参数

lambda表达式

  • 格式

    [capture list](param list) -> return type {function body}
  • 混合使用隐式捕获和显示捕获时,捕获列表第一个参数是默认捕获形式,如果第一个为隐式捕获,则其后所有参数需为显示捕获,反之亦然。
  • 可变lambda
    • 默认情况下,对于一个值被拷贝的变量,lambda不会改变其值,如果想要改变被捕获的变量的值,需要在参数列表首加上mutable关键字,例如:

      void foo()
      {
      	size_t v1 = 42;
      	auto f = [v1] () mutable {return ++v1;}
      	v1 = 0;
      	auto j = f(); // 此时j为43
      }

标准库bind函数

  • 可以将bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
  • 调用形式

    auto newCallable = bind(callable, arg_list);
  • arg_list中的参数可能包含形如_n的名字,其中n是一个整数。这些参数是“占位符”,表示newCallable的参数。数值n表示生成的可调用对象中参数的位置,_1为newCallable的第一个参数,-2为第二个参数,以此类推。
    • _n定义在名为placeholders的命名空间中,这个命名空间定义在std照片。头文件与bind一致,为functional
  • 绑定引用参数
    • 默认情况下,bind的那些不是占位符的参数会被拷贝到bind返回的可调用对象中,但是有时候需要绑定引用,则需使用:ref函数。

      for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' '));
    • 函数ref返回一个对象,包含给定的引用,此对象可拷贝。标准库还有一个cref函数,生成一个保存const引用的类。
  • 关于bind1stbind2nd:二者与bind函数类似,但是由于局限性太强,新版C++标准已弃用。


目录