c++oding="utf-8" ?>
std::ranges::count要求范围支持迭代器且元素可比较,依赖operator==或自定义谓词,不支持lambda条件匹配,适用于vector、string等容器的值统计,需c++20标准和头文件。

std::ranges::count 要求范围必须支持迭代器,且元素可比较
它不是万能的“计数黑盒”,底层依赖 operator== 或自定义谓词,所以被统计类型必须能和给定值比较。比如 std::vector<:string></:string> 可以直接用,但若容器里是自定义类且没重载 operator==,编译会失败,报错类似:invalid operands to binary expression ('MyType' and 'const T')。
常见使用场景包括:统计 vector 中某个整数出现次数、查找 string 中特定字符频次、检查 array 是否全为某默认值。
- 必须传入一个范围(
std::ranges::range概念满足者),不能传裸指针+长度 - 第二个参数是待匹配的值(
const T&),不是迭代器或函数对象 - 不支持传入 lambda 做条件匹配 —— 那得用
std::ranges::count_if
正确调用 std::ranges::count 的三种典型写法
注意命名空间和 C++20 标准要求:头文件是 <algorithm></algorithm>,不是 <ranges></ranges>;且需开启 C++20(如 GCC/Clang 加 -std=c++20)。
示例一:基础数值统计
#include <algorithm>
#include <vector>
#include <iostream>
int main() {
std::vector<int> v = {1, 2, 3, 2, 4, 2};
auto n = std::ranges::count(v, 2); // 返回 3
std::cout
<p>示例二:字符串中字符计数</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/gongju/2823" title="C++14"><img
src="https://img.php.cn/upload/manual/001/431/639/6ac8b33c327c4749.png" alt="C++14" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="overflowclass">C++14</a>
<p class="overflowclass">C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。</p>
</div>
<a rel="nofollow" href="/xiazai/gongju/2823" title="C++14" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<pre class="brush:php;toolbar:false;">std::string s = "hello world";
auto cnt = std::ranges::count(s, 'l'); // 返回 3
示例三:自定义类型(前提是重载了 operator==)
struct Point { int x, y; };
bool operator==(const Point& a, const Point& b) { return a.x == b.x && a.y == b.y; }
std::vector<point> pts = {{1,2}, {3,4}, {1,2}};
auto c = std::ranges::count(pts, Point{1,2}); // 返回 2</point>
std::ranges::count 和 std::count 的关键区别在哪
最直接的区别是参数形式:std::count 接收一对迭代器(first, last),而 std::ranges::count 接收一个范围(比如容器本身)加一个值。
这意味着:
- 用
std::ranges::count时,无法只统计子区间(比如 vector 的中间 5 个元素),除非先用std::ranges::subrange或视图切片(如v | std::views::drop(2) | std::views::take(5))构造新范围 -
std::ranges::count对std::initializer_list、C 风格数组(如int arr[5])、std::string_view等都天然支持,无需手动取begin/end - 性能上无本质差异,都是 O(n),但 ranges 版本少写两个参数,可读性略高
容易踩的坑:编译失败、返回 0、或者根本没生效
最常见的三个问题:
- 忘记开启 C++20:编译器报
'ranges' is not a namespace-name或找不到count—— 检查编译选项和标准库版本(libstdc++ ≥ 11 / libc++ ≥ 14) - 传入了右值临时对象:比如
std::ranges::count(std::vector{1,2,3}, 2)在某些标准库实现中可能因绑定临时对象到 const 引用而引发 lifetime 问题,建议先存为变量再传 - 类型不匹配导致隐式转换失败:比如对
std::vector<long></long>传int值,某些编译器可能拒绝推导,显式写成std::ranges::count(v, 2L)更稳妥
真正要注意的是:它只做值匹配,不支持模式、正则、部分比较。想统计“大于 5 的元素个数”?必须换 std::ranges::count_if 并传 lambda。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










