C++23的contains是关联容器(如set、unordered_set)的成员函数,非全局算法,不适用于vector等序列容器;需用std::find或std::binary_search替代,且必须启用C++23标准并确保标准库支持。

contains函数在C++23中只存在于std::unordered_set、std::set等关联容器,不适用于std::vector或std::array
很多人搜“C++ contains函数”是想替代std::find做存在性检查,但C++23的contains不是通用算法,而是容器成员函数。它只被添加到标准关联容器(set、unordered_set、map、unordered_map)中,且仅用于键查找——比如my_set.contains(x),不能写std::contains(my_vec, x)(这在C++23里根本不存在)。
常见错误现象:error: 'contains' is not a member of 'std::vector' 或编译器报no matching function for call to 'contains',基本都是误以为它是全局函数或泛型算法。
-
std::vector、std::string、std::array等序列容器仍需用std::find+!= end() -
std::map和std::unordered_map的contains查的是key,不是value;查value仍得遍历 - 必须开启C++23标准:编译时加
-std=c++23(GCC 13+ / Clang 16+),旧版本即使写了也不会识别
怎么正确调用std::set::contains和std::unordered_set::contains
调用方式统一为container.contains(key),返回bool,语义清晰、比find != end()少写且更高效(尤其对unordered_set,避免构造迭代器)。
#include <set>
#include <unordered_set>
std::set<int> s = {1, 3, 5, 7};
std::unordered_set<std::string> us = {"a", "b", "c"};
bool b1 = s.contains(5); // true
bool b2 = us.contains("x"); // false
- 参数类型必须严格匹配key_type,不会隐式转换(比如
const char*传给std::unordered_set<std::string>会失败) - 对
std::map,m.contains(k)等价于m.find(k) != m.end(),不触发mapped_type的构造 - 性能上,
contains比count更合适——后者对multiset有意义,但普通set用count只是多绕一层
为什么std::vector没有contains?替代方案怎么选
C++标准委员会明确拒绝为序列容器添加成员版contains,理由是:序列容器的查找本质是线性扫描,放在算法层更正交;强行塞进容器接口会破坏设计一致性。
立即学习“C++免费学习笔记(深入)”;
所以你得继续用算法:
- 最常用:
std::find(v.begin(), v.end(), x) != v.end() - 如果容器已排序,用
std::binary_search(v.begin(), v.end(), x)(更快,O(log n)) - C++23起可配合
std::ranges::find写成std::ranges::find(v, x) != v.end(),稍简洁但没实质性能提升 - 别用
std::any_of(v.begin(), v.end(), [&](auto& e){ return e == x; })——可读性差,且编译器未必能优化掉lambda开销
容易被忽略的兼容性细节
哪怕开了-std=c++23,某些场景下contains仍不可用:
- libstdc++(GCC)需GNU libstdc++ ≥ 13.1;早期C++23支持版本可能只实现了部分容器(比如有
set::contains但没unordered_map::contains) - MSVC 19.35+ 支持完整,但需确认项目设置中“C++语言标准”设为“ISO C++23 Standard (/std:c++23)”而非“Latest”
- Clang 16默认不启用C++23新特性,必须显式加
-std=c++23且链接对应libc++版本 - 模板实例化时若key类型未定义
operator==(对unordered_*还需std::hash),错误信息可能指向contains内部,实际问题在类型本身
真正要小心的不是语法怎么写,而是编译环境是否真的交付了那个函数——先跑个最小测试用例验证,比翻文档更快。


















