如何排序unique_ptr列表?现有代码因拷贝构造函数删除编译失败
你的推测完全正确!std::unique_ptr的拷贝构造函数确实被显式删除了——这正是你代码编译失败的根源。
咱们来拆解一下问题:你写的ptrLess函数参数是按值传递的unique_ptr<int>,这意味着调用这个函数时会尝试拷贝传入的unique_ptr,但unique_ptr是独占所有权的智能指针,设计上就不允许拷贝(否则会出现多个指针指向同一块内存,析构时重复释放的问题),所以编译器直接抛出了那个删除函数的错误。
接下来给你几种可行的解决方案,都能实现unique_ptr列表的排序:
方案1:修改比较函数为引用传递
把比较函数的参数改成const左值引用,这样就不会触发拷贝,只是引用原有的unique_ptr对象:
bool ptrLess(const unique_ptr<int>& ptr1, const unique_ptr<int>& ptr2) { return *ptr1 < *ptr2; }
这样调用list.sort(ptrLess)时,只会传递引用,完全不会涉及拷贝操作,完美避开了删除的拷贝构造函数。
方案2:使用lambda表达式(更简洁)
不需要单独定义比较函数,直接在sort调用里写lambda,同样用引用参数:
myList.sort([](const unique_ptr<int>& a, const unique_ptr<int>& b) { return *a < *b; });
这种方式更紧凑,也符合现代C++的写法。
额外注意:容器插入时的移动语义
另外你原来的代码里还有个小坑:变量名用了list,这会和std::list冲突,建议改成myList这类名字。而且往列表里push_back的时候,也需要用std::move来转移unique_ptr的所有权,否则同样会触发拷贝错误:
myList.push_back(std::move(ptr1)); myList.push_back(std::move(ptr2)); myList.push_back(std::move(ptr3));
完整可编译代码
把这些修改整合后,完整代码如下:
#include <iostream> #include <list> #include <memory> using namespace std; bool ptrLess(const unique_ptr<int>& ptr1, const unique_ptr<int>& ptr2) { return *ptr1 < *ptr2; } int main() { unique_ptr<int> ptr1(new int(3)); unique_ptr<int> ptr2(new int(2)); unique_ptr<int> ptr3(new int(5)); list<unique_ptr<int>> myList; myList.push_back(std::move(ptr1)); myList.push_back(std::move(ptr2)); myList.push_back(std::move(ptr3)); myList.sort(ptrLess); // 或者用lambda:myList.sort([](const auto& a, const auto& b) { return *a < *b; }); for (auto &element : myList) { cout << *element << " "; } return 0; }
运行这段代码会输出2 3 5,完全符合预期。
至于你提到的移动构造函数——其实我们在push_back的时候已经用到了,排序本身不需要移动unique_ptr的所有权,只需要访问它们指向的值,所以用引用传递比较函数参数是最直接高效的方案。
内容的提问来源于stack exchange,提问作者Zach

