以下代码无法编译:
bool ptrLess(unique_ptr<int> ptr1, 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>> list;
list.push_back(ptr1);
list.push_back(ptr2);
list.push_back(ptr3);
list.sort(ptrLess);
for (auto &element : list) {
cout << *element;
}
return 0;
}
我认为这是因为删除了unique_ptr
的复制构造函数。我得到一个错误:
错误C2280: “的std ::的unique_ptr&GT; ::的unique_ptr(常量 的std ::的unique_ptr&LT; _Ty,性病:: default_delete&LT; _Ty&GT;&GT; &amp;)':试图 引用已删除的功能
有没有办法对unique_ptr
的列表进行排序,可能是使用移动构造函数?
答案 0 :(得分:5)
你应该使用const ref - 毕竟你不想修改这些指针:
bool ptrLess(const unique_ptr<int>& ptr1, const unique_ptr<int>& ptr2)
如果您的list
模板为std::list
,那么将参数作为r值参考传递无法正常工作 - list::sort
必须致电std::move
才能有效地重置您的指针。
修改强>
至于列表的其余代码:std::list
有一个名为emplace_back
(和emplace_front
)的方便方法,它允许您在原地构建和附加元素:
your_list.emplace_back(new int(2));
答案 1 :(得分:1)
试试这个:
#include <memory>
#include <list>
#include <iostream>
using namespace ::std;
bool ptrLess(unique_ptr<int>& ptr1, 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>> list;
list.push_back(move(ptr1));
list.push_back(move(ptr2));
list.push_back(move(ptr3));
list.sort(ptrLess);
for (auto &element : list) {
cout << *element;
}
return 0;
}
这里的问题是你需要了解unique_ptr
实际上的目标:
当处理指针/引用时,如果存在指向同一对象的多个指针/引用,则会出现很多潜在的问题。
unique_ptr
试图避免这种情况。
因此,您无法创建引用同一对象的2 unique_ptr
。
您无法使用ptrLess()
功能,因为将其称为
unique_ptr<int> ptr1(new int(3));
unique_ptr<int> ptr2(new int(2));
ptrLess(ptr1, ptr2);
因为这意味着ptr1
ptr2
必须被复制并传递给ptrLess()
- 这里的关键字是&#39;按值调用&#39;。< / p>
而且,你做不到
list<unique_ptr<int>> list;
unique_ptr<int> ptr1(new int(3));
unique_ptr<int> ptr1(new int(3));
因为这也是必须创建ptr1
的副本。
这里的解决方案是不将unique_ptr
s作为值传递给ptrLess
,而是作为参考:
bool ptrLess(unique_ptr<int>& ptr1, unique_ptr<int>& ptr2);
你没有将副本传递到列表中,但移动你的对象:
list.push_back(move(ptr1));
这里的关键字是&#39; move-semantics&#39;。
这将使ptr1
变量的内容无效 - 该对象已从ptr1
移出到列表中。
如果您对这些事情更感兴趣,我建议您查看Rust语言;)
正如Baum mit Augen指出的那样,ptrLess
的参数最好被声明为const
:
bool ptrLess(const unique_ptr<int>& ptr1, const unique_ptr<int>& ptr2);
答案 2 :(得分:-1)
尝试传递const ref,这样就不会复制参数: bool ptrLess(const unique_ptr&amp; ptr1,const unique_ptr&amp; ptr2){return * ptr1&lt; * PTR2; }
答案 3 :(得分:-1)
我认为,如果OP使用shared_ptr
代替unique_ptr
,那么原先发布的代码将以其他方式保持不变:
#include <memory>
#include <list>
#include <iostream>
using namespace ::std;
bool ptrLess(const shared_ptr<int>& ptr1, const shared_ptr<int>& ptr2)
{
return *ptr1 < *ptr2;
}
int main()
{
shared_ptr<int> ptr1(new int(3));
shared_ptr<int> ptr2(new int(2));
shared_ptr<int> ptr3(new int(5));
list<const shared_ptr<int>> list;
list.push_back(ptr1);
list.push_back(ptr2);
list.push_back(ptr3);
list.sort(ptrLess);
for (auto &element : list) {
cout << *element;
}
return 0;
}
在Wandbox上运行。
从某种意义上说,这是一种一贯的做事方式。 push_back
通常会复制正在添加到列表中的对象,如果原始对象仍然可以使用,则他或她想要使用它。使用shared_ptr
具有类似的语义,而没有复制对象本身的开销。相反,只复制shared_ptr
,这是一个便宜的操作。
此外,将OP的原始代码修改为move
unique_ptrs
进入列表本身就很脆弱。它们仍然在调用者的范围内,但不再可用。如果你尝试,你会得到(我假设)nullptr
解除引用。那么,最好这样做(注意额外的括号):
...
list<unique_ptr<int>> list;
{
unique_ptr<int> ptr1(new int(3));
unique_ptr<int> ptr2(new int(2));
unique_ptr<int> ptr3(new int(5));
list.push_back(move(ptr1));
list.push_back(move(ptr2));
list.push_back(move(ptr3));
}
...
现在你很安全。
在那里,这是一个比原版更好的帖子,对不起。