C++编译报错,pair元素类型中包含unique_ptr,调用pair、unique_ptr的默认拷贝构造函数,导致编译失败

Sheldon
  • 24

代码如下:

#include <algorithm>
#include <iostream>
#include <set>
#include <string>
#include <memory>
#include <vector>

int main() {
    typedef std::pair<int, std::unique_ptr<std::string>> Entry;
    typedef std::set<Entry> TimerList;
    TimerList timers_;

    std::vector<Entry> expired;
    Entry sentry = std::make_pair(5, std::move(std::unique_ptr<std::string>(new std::string("555"))));
    TimerList::iterator it = timers_.lower_bound(sentry);

    for (TimerList::iterator begin = timers_.begin(); begin != it; ++begin)
    {
        expired.push_back(std::move(*begin));
    }
}

编译报错:

In file included from /usr/include/x86_64-linux-gnu/c++/4.9/bits/c++allocator.h:33:0,
                 from /usr/include/c++/4.9/bits/allocator.h:46,
                 from /usr/include/c++/4.9/string:41,
                 from /usr/include/c++/4.9/random:40,
                 from /usr/include/c++/4.9/bits/stl_algo.h:66,
                 from /usr/include/c++/4.9/algorithm:62,
                 from test.cpp:1:
/usr/include/c++/4.9/ext/new_allocator.h: In instantiation of ‘void __gnu_cxx::new_allocator< <template-parameter-1-1> >::construct(_Up*, _Args&& ...) [with _Up = std::pair<int, std::unique_ptr<std::basic_string<char> > >; _Args = {const std::pair<int, std::unique_ptr<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::default_delete<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&}; _Tp = std::pair<int, std::unique_ptr<std::basic_string<char> > >]’:
/usr/include/c++/4.9/bits/alloc_traits.h:527:4:   required from ‘static void std::allocator_traits<std::allocator<_Tp> >::construct(std::allocator_traits<std::allocator<_Tp> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<int, std::unique_ptr<std::basic_string<char> > >; _Args = {const std::pair<int, std::unique_ptr<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::default_delete<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > > >&}; _Tp = std::pair<int, std::unique_ptr<std::basic_string<char> > >; std::allocator_traits<std::allocator<_Tp> >::allocator_type = std::allocator<std::pair<int, std::unique_ptr<std::basic_string<char> > > >]’
/usr/include/c++/4.9/bits/stl_vector.h:918:34:   required from ‘void std::vector<_Tp, _Alloc>::push_back(const value_type&) [with _Tp = std::pair<int, std::unique_ptr<std::basic_string<char> > >; _Alloc = std::allocator<std::pair<int, std::unique_ptr<std::basic_string<char> > > >; std::vector<_Tp, _Alloc>::value_type = std::pair<int, std::unique_ptr<std::basic_string<char> > >]’
test.cpp:19:44:   required from here
/usr/include/c++/4.9/ext/new_allocator.h:120:4: error: use of deleted function ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = std::unique_ptr<std::basic_string<char> >]’
  { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    ^
In file included from /usr/include/c++/4.9/utility:70:0,
                 from /usr/include/c++/4.9/algorithm:60,
                 from test.cpp:1:
/usr/include/c++/4.9/bits/stl_pair.h:127:17: note: ‘constexpr std::pair<_T1, _T2>::pair(const std::pair<_T1, _T2>&) [with _T1 = int; _T2 = std::unique_ptr<std::basic_string<char> >]’ is implicitly deleted because the default definition would be ill-formed:
       constexpr pair(const pair&) = default;
                 ^
/usr/include/c++/4.9/bits/stl_pair.h:127:17: error: use of deleted function ‘std::unique_ptr<_Tp, _Dp>::unique_ptr(const std::unique_ptr<_Tp, _Dp>&) [with _Tp = std::basic_string<char>; _Dp = std::default_delete<std::basic_string<char> >]’
In file included from /usr/include/c++/4.9/memory:81:0,
                 from test.cpp:5:
/usr/include/c++/4.9/bits/unique_ptr.h:356:7: note: declared here
       unique_ptr(const unique_ptr&) = delete;

编译报错的原因大概是调用push_back的时候,调用pair默认构造函数,然后会调用unique_ptr的拷贝构造,导致失败。

代码的目的是想要将timers_的元素拷贝到expired去,有什么方法可以实现拷贝std::pair<int, std::unique_ptr<std::string>> Entry这种类型(pair的元素包含unique_ptr)的吗?

回复
阅读 3.1k
1 个回答
✓ 已被采纳

std::unique_ptr 不能 copy ,只能 move 。

含有一个 std::unique_ptrstd::pair 也是这样。

expired.push_back(std::move(*begin));,这里,你确实是在试图 move ,但是,由于 std::set 的 iterator 是不可修改的,只能 copy ,所以最终还是选择了 copy 而不是 move 。但是你的 pair 不能 copy ,于是败了。


注1:associative.reqmts-6 :

iteratorof an associative container is of the bidirectional iterator category. For associative containers where the value type is the same as the key type, both iterator and const_­iterator are constant iterators. ......
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
宣传栏