2017-08-27 119 views
2

多年後回到C++;試圖追趕C++ 11 & 14.我讀過rvalues和移動語義。我以爲我理解了這個概念。顯然不是。我看了幾十個例子。但我根本無法讓我的代碼編譯。我必須在示例中錯過某些明顯的東西。由於unique_ptr<int>有一個用戶聲明的移動ctor,我總是會得到有關複製ctor被刪除的錯誤。顯然我對這個概念缺少了一些東西,但我無法弄清楚它是什麼。這裏的代碼,精簡到它的本質:擊敗向量<unique_ptr>

#include <memory> 
#include <utility> 
#include <vector> 

int main(int, char*[]) { 
    auto oneInt{std::make_unique<int>(0)}; 
    auto someInts{std::vector<std::unique_ptr<int>>{std::move(oneInt)}}; 

    return 0; 
} 

我做錯了什麼?

編輯:以下是此特定代碼的錯誤。請注意,我已經嘗試了可以​​考慮的各種代碼變體,結果各不相同,但基本問題始終是相同的:複製ctor被刪除,因爲unique_ptr<int>具有用戶聲明的移動ctor。

編輯:我已將代碼更新爲#include <memory>,並粘貼了新的錯誤。我只能希望問題是那樣的愚蠢。

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1752:31: error: call to implicitly-deleted copy constructor of 
     'std::__1::unique_ptr<int, std::__1::default_delete<int> >' 
      ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...); 
          ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1668:18: note: in instantiation of function template 
     specialization 'std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > >::construct<std::__1::unique_ptr<int, std::__1::default_delete<int> >, 
     const std::__1::unique_ptr<int, std::__1::default_delete<int> > &>' requested here 
      {__a.construct(__p, _VSTD::forward<_Args>(__args)...);} 
       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1514:14: note: in instantiation of function template 
     specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::__construct<std::__1::unique_ptr<int, 
     std::__1::default_delete<int> >, const std::__1::unique_ptr<int, std::__1::default_delete<int> > &>' requested here 
      {__construct(__has_construct<allocator_type, _Tp*, _Args...>(), 
      ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1598:17: note: in instantiation of function template 
     specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::construct<std::__1::unique_ptr<int, 
     std::__1::default_delete<int> >, const std::__1::unique_ptr<int, std::__1::default_delete<int> > &>' requested here 
       construct(__a, _VSTD::__to_raw_pointer(__begin2), *__begin1); 
       ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1024:21: note: in instantiation of function template 
     specialization 'std::__1::allocator_traits<std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::__construct_range_forward<const 
     std::__1::unique_ptr<int, std::__1::default_delete<int> > *, std::__1::unique_ptr<int, std::__1::default_delete<int> > *>' requested here 
    __alloc_traits::__construct_range_forward(__a, __first, __last, this->__end_); 
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/vector:1285:9: note: in instantiation of function template 
     specialization 'std::__1::vector<std::__1::unique_ptr<int, std::__1::default_delete<int> >, std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > 
     > >::__construct_at_end<const std::__1::unique_ptr<int, std::__1::default_delete<int> > *>' requested here 
     __construct_at_end(__il.begin(), __il.end(), __il.size()); 
     ^
virtual.cpp:7:21: note: in instantiation of member function 'std::__1::vector<std::__1::unique_ptr<int, std::__1::default_delete<int> >, 
     std::__1::allocator<std::__1::unique_ptr<int, std::__1::default_delete<int> > > >::vector' requested here 
     auto someInts{std::vector<std::unique_ptr<int>>{std::move(oneInt)}}; 
        ^
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:2621:31: note: copy constructor is implicitly deleted because 
     'unique_ptr<int, std::__1::default_delete<int> >' has a user-declared move constructor 
    _LIBCPP_INLINE_VISIBILITY unique_ptr(unique_ptr&& __u) _NOEXCEPT 
+4

當問構建錯誤通常有助於看到的錯誤。您能否編輯您的問題以包含來自版本的完整,完整和未修改的輸出,包括文本和任何可能的信息說明? –

+4

其中之一,你沒有包含''標題。 – StoryTeller

+2

'oneInt'被移到初始化列表中,但被複製出來。 – molbdnilo

回答

6

你的代碼有很多問題。首先,有一個過度使用{}初始化混淆了事情。使用auto是好的,但auto x{...};聲明充滿危險,因爲auto x{single_value}的含義已經隨時間而改變。在合理的情況下最好使用auto x = single_value;語法。

其次,您不能通過{}初始化程序列表將unique_ptr插入到容器中。完全一樣。經過std::initializer_list的物品必須可複製,而unique_ptr則不可複製。

你想要的是這樣的:

auto oneInt = std::make_unique<int>(0); 
std::vector<std::unique_ptr<int>> someInts; 
someInts.push_back(std::move(oneInt)); 
+1

*通過std :: initializer_list的項目必須是可複製的* - 這! – GreatBigBore

+0

不確定,如果'someInts.push_back(std :: move(oneInt))'是正確的事情。在第一個「移動」之後,'oneInt'裏面會有什麼?沒有! –

+1

@SemyonBurov:好主意或不好,它符合OP提供的代碼的意圖。 –

2

簡短的回答是,一個std::initializer_list包含值;他們不能被移出,只能從中複製。清楚的是,如果您使用vector的構造的initializer_list表單,則列表中的項目將被複制到向量中。

See this thread討論您確切的問題和一些建議的解決方法。