2013-01-22 67 views
5

我有一個簡單的C++ std :: vector,它裏面存儲着如下所示的線程。你能解釋爲什麼在編譯過程中評論「不編譯」的行顯示錯誤?而爲什麼評論「編譯」的工作線?vector的push_back錯誤背後的原因

#include<thread> 
#include<vector> 

using namespace std; 
void abc() {} 
int main() 
{ 
    vector<thread> workers; 
    workers.push_back(thread(abc)); // compiles 
    thread t(abc); 
    workers.push_back(t); // does not compile 

    return 0; 
} 

更新:我在linux上使用g ++ 4.4.6。下面是你得到了錯誤的錯誤

[[email protected] c++]$ g++ -std=c++0x -pthread -g -Wall t.cpp -o t 
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/x86_64-redhat-linux/bits/c++allocator.h:34, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/allocator.h:48, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/string:43, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/locale_classes.h:42, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/ios_base.h:43, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ios:43, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ostream:40, 
       from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/iostream:40, 
       from t.cpp:1: 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread: In member function ‘void __gnu_cxx::new_allocator<_Tp>::construct(_Tp*, const _Tp&) [with _Tp = std::thread]’: 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h:737: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::thread, _Alloc = std::allocator<std::thread>]’ 
t.cpp:29: instantiated from here 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:122: error: deleted function ‘std::thread::thread(const std::thread&)’ 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/ext/new_allocator.h:105: error: used here 
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/vector:69, 
       from t.cpp:4: 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread: In member function ‘void std::vector<_Tp, _Alloc>::_M_insert_aux(__gnu_cxx::__normal_iterator<typename std::_Vector_base<_Tp, _Alloc>::_Tp_alloc_type::pointer, std::vector<_Tp, _Alloc> >, _Args&& ...) [with _Args = const std::thread&, _Tp = std::thread, _Alloc = std::allocator<std::thread>]’: 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/stl_vector.h:741: instantiated from ‘void std::vector<_Tp, _Alloc>::push_back(const _Tp&) [with _Tp = std::thread, _Alloc = std::allocator<std::thread>]’ 
t.cpp:29: instantiated from here 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/thread:122: error: deleted function ‘std::thread::thread(const std::thread&)’ 
/usr/lib/gcc/x86_64-redhat-linux/4.4.6/../../../../include/c++/4.4.6/bits/vector.tcc:314: error: used here 
+2

當問編譯/鏈接錯誤,你需要* *張貼*整,未經編輯*錯誤消息。 – Angew

+1

如果您發佈_compilable_示例,它也會有所幫助。我知道'std :: vector'是什麼,但不是簡單的'vector'。 –

+0

@JoachimPileborg通過使用命名空間std – Jimm

回答

13

因爲std::thread不可複製,和你想插入的t拷貝到載體中。

你可以做這項工作的唯一方法是做:

workers.push_back(std::move(t)); 

然而,這將意味着你這樣做之後,t不再代表一個線程(它代表的線程移入向量)。

+0

修復它如何插入參考? – Jimm

+0

即使他沒有插入副本(即放置),「std :: vector」仍然需要重新分配其內存塊的能力,這需要移動或複製。 – Potatoswatter

+0

@Potatoswatter但是,'std :: thread'是可移動的,所以它可以被插入到'std :: vector'中。 – Angew

1

原因是std::thread有一個移動構造函數,但沒有複製構造函數。

1

因爲std::thread可複製,你可以將它移到雖然矢量:

thread t(abc); 
    workers.push_back(std::move(t)); 

更好的解決方案是保存在向量智能指針:

std::vector<std::shared_ptr<std::thread>> workers; 

因爲當與拉姆達的工作,沒有辦法捕獲僅移動類型,解決方法是在std::shared_ptr<std::thread>中存儲移動類型。

+0

您會詳細說明爲什麼您在這種情況下更好地考慮動態分配? – Angew

+0

我還是不太明白。 [lambda](http://ideone.com/jtS60U)有什麼問題? – Angew

2

這裏是一個更清潔,更快速的解決方案,既不需要複製,也不動:

workers.emplace_back(abc);