Pertanyaan apa alasan di balik kesalahan push_back vektor


Saya memiliki c ++ std :: vector sederhana dan di dalamnya, saya menyimpan utas seperti yang ditunjukkan di bawah ini. Bisakah Anda jelaskan mengapa baris dengan komentar "tidak dikompilasi" menunjukkan kesalahan selama kompilasi? Dan mengapa baris dengan komentar "mengkompilasi" berfungsi?

#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;
 }

UPDATE: saya menggunakan g ++ 4.4.6 di linux. Di bawah ini adalah kesalahan

[jim@cola 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

5
2018-01-22 08:23


asal


Jawaban:


Anda mendapatkan kesalahan karena std::thread aku s tidak dapat dibagikan, dan Anda mencoba memasukkan salinannya t ke dalam vektor.

Satu-satunya cara Anda dapat melakukan pekerjaan ini adalah:

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

Namun, ini berarti setelah Anda melakukan itu, t tidak lagi mewakili utas (untaian yang diwakilinya dipindahkan ke vektor).


13
2018-01-22 08:27



Berikut ini adalah solusi yang lebih bersih dan lebih cepat yang tidak membutuhkan penyalinan atau pemindahan:

workers.emplace_back(abc);

2
2018-01-22 10:20



Alasannya adalah itu std::thread memiliki konstruktor bergerak, tetapi tidak memiliki konstruktor salinan.


1
2018-01-22 08:28



Karena std::thread tidak bisa ditagih, Anda bisa memindahkannya ke vektor meskipun:

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

Solusi yang lebih baik adalah dengan menyimpan pointer pintar dalam vektor:

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

Karena ketika bekerja dengan lambda, tidak ada cara untuk menangkap satu-satunya jenis pemindahan, solusi adalah untuk menyimpan jenis bergerak saja di std::shared_ptr<std::thread>.


1
2018-01-22 08:28