如何对存储std::unique_ptr的vector使用std::find_if算法并解决编译报错?
问题根因
代码编译失败的核心原因:
std::unique_ptr是独占所有权的智能指针,拷贝构造函数被隐式删除,不存在可调用的实例拷贝逻辑- 原代码中
std::find_if的lambda表达式采用值传递定义参数IntegerPtr s:算法遍历容器元素时,会尝试将容器内的unique_ptr元素拷贝一份传入lambda形参,直接触发被删除的拷贝构造函数,引发编译报错 - 原代码对
std::find_if的返回值处理存在逻辑错误:该算法返回的是指向匹配元素的迭代器,并非直接返回unique_ptr实例,无法直接在迭代器上调用.get()方法
修正方法
- 将lambda的形参从值传递改为
const IntegerPtr&常量左值引用:遍历过程不需要拷贝unique_ptr实例,仅通过引用读取指向对象的成员值,完全避开拷贝构造的调用 - 对
std::find_if的返回值先做有效性校验:确认迭代器没有指向容器尾部后,再解引用拿到对应元素的unique_ptr实例进行后续操作,避免访问非法内存
修正后可运行的完整代码
#include <iostream> #include <vector> #include <memory> #include <algorithm> class Integer { public: explicit Integer(int i): i_(i){}; int get() const{ return i_; } private: int i_; }; using IntegerPtr = std::unique_ptr<Integer>; int main() { IntegerPtr p1 = std::make_unique<Integer>(4); IntegerPtr p2 = std::make_unique<Integer>(5); IntegerPtr p3 = std::make_unique<Integer>(6); std::vector<IntegerPtr> vectorOfIntegerPointers({ std::move(p1), std::move(p2), std::move(p3), }); int i = 5; auto match_iter = std::find_if( vectorOfIntegerPointers.begin(), vectorOfIntegerPointers.end(), // 用const左值引用接收元素,不触发拷贝 [&](const IntegerPtr& s) { return s->get() > i; } ); // 校验迭代器有效性,避免访问容器尾后地址的未定义行为 if (match_iter != vectorOfIntegerPointers.end()) { // 先解引用迭代器拿到unique_ptr,再获取指向的原始值 std::cout << (*match_iter)->get() << std::endl; } else { std::cout << "No element matches the condition" << std::endl; } return 0; }
通用注意事项
对存储
std::unique_ptr这类独占智能指针的容器,所有遍历类STL算法的可调用对象,都优先采用常量左值引用接收容器元素,禁止使用值传递方式定义形参,否则必然触发unique_ptr拷贝构造被删除的编译错误。
内容的提问来源于stack exchange,提问作者CiaranWelsh
相关产品推荐
相关产品推荐

