向std::list中emplace std::unique_ptr出现编译错误,求解决方法
问题:将std::unique_ptr放入std::list时出现编译错误
编译错误信息
<source>:29:23: error: no matching function for call to 'std::__cxx11::list<std::unique_ptr<test> >::emplace(std::remove_reference<std::unique_ptr<test>&>::type)' 29 | mapList[1].emplace(std::move(t));
相关代码
using namespace std; class test { public: int i; }; typedef std::list<std::unique_ptr<test>> testList; int main() { unordered_map<int, testList> mapList; mapList.try_emplace(1, testList()); std::unique_ptr<test> t = make_unique<test>(); mapList[1].emplace(std::move(t)); return 0; }
解决方案
错误根源是误用了std::list::emplace函数:
std::list::emplace的第一个参数必须是插入位置的迭代器(比如list.end()),后续参数才是构造元素所需的参数;- 如果你想直接在list尾部添加已有的
std::unique_ptr(通过移动语义),应该使用emplace_back或push_back,这两个函数不需要指定位置参数。
修改后的代码(两种可选方式)
方式1:使用emplace_back
using namespace std; class test { public: int i; }; typedef std::list<std::unique_ptr<test>> testList; int main() { unordered_map<int, testList> mapList; mapList.try_emplace(1, testList()); std::unique_ptr<test> t = make_unique<test>(); mapList[1].emplace_back(std::move(t)); // 替换emplace为emplace_back return 0; }
方式2:使用push_back
// ... 其余代码与原代码一致 mapList[1].push_back(std::move(t));
两者的区别:emplace_back是就地构造元素(这里用右值引用构造unique_ptr),push_back是移动构造元素,对于unique_ptr来说最终效果一致。
如果确实需要在指定位置插入元素,可以给emplace传递迭代器参数,比如:
mapList[1].emplace(mapList[1].begin(), std::move(t));
内容的提问来源于stack exchange,提问作者51k
相关产品推荐
相关产品推荐

