Próbuję zbudować std::thread
z funkcją członka, która nie przyjmuje argumentów i zwraca void
. Nie mogę znaleźć żadnej składni, która działa - kompilator narzeka bez względu na wszystko. Jaki jest prawidłowy sposób zaimplementowania spawn()
, std::thread
aby zwracał wykonanie test()
?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};
c++
multithreading
c++11
abergmeier
źródło
źródło
std::move( std::thread(func) );
jest lepsze,std::thread
ponieważ nie ma konstruktora kopiowania.std::move
w tym przypadku użycie jest redundantne - gdyby nie było to prawdą i nie istniałby konstruktor kopiowania, kompilator i tak dałby błąd.Odpowiedzi:
EDYCJA: Uwzględniając swoją edycję, musisz to zrobić w następujący sposób:
AKTUALIZACJA: Chcę wyjaśnić kilka innych kwestii, niektóre z nich zostały również omówione w komentarzach.
Opisana powyżej składnia jest zdefiniowana w kategoriach INVOKE (§20.8.2.1):
Innym ogólnym faktem, na który chcę zwrócić uwagę, jest to, że domyślnie konstruktor wątków kopiuje wszystkie przekazane mu argumenty. Powodem tego jest to, że argumenty mogą potrzebować przeżyć wątek wywołujący, kopiowanie argumentów gwarantuje to. Zamiast tego, jeśli naprawdę chcesz przekazać referencję, możesz użyć
std::reference_wrapper
utworzonego przezstd::ref
.Robiąc to, obiecujesz, że zadbasz o to, aby argumenty nadal istniały, gdy wątek na nich działa.
Pamiętaj, że wszystkie wyżej wymienione rzeczy można również zastosować do
std::async
istd::bind
.źródło
std::thread
konstruktora działa tak, jakby argumenty zostały przekazanestd::bind
. Aby wywołać funkcję członka, pierwszym argumentemstd::bind
musi być wskaźnik, odwołanie lub wskaźnik współdzielony do obiektu odpowiedniego typu.bind
? Nigdzie nie mogę tego znaleźć.Ponieważ używasz C ++ 11, wyrażenie lambda jest ładnym i czystym rozwiązaniem.
ponieważ
this->
można go pominąć, można go skrócić do:Lub tylko
źródło
std::move
zwracania zmiennej lokalnej według wartości. To faktycznie hamuje RVO. Jeśli po prostu zwrócisz wartość (bez przeniesienia), kompilator może użyć RVO, a jeśli nie, standard mówi, że musi wywoływać semantykę przenoszenia.[=]
. Dzięki temu możesz przypadkowo skopiować ogromny obiekt. Ogólnie rzecz biorąc, jest to zapach zapachowy do użycia[&]
lub[=]
.[&]
), możesz wprowadzić błędy, takie jak niektóre wiszące referencje. (Na przykładstd::thread spawn() { int i = 10; return std::thread( [&] { std::cout<<i<<"\n"; } ); }
)Oto kompletny przykład
Kompilacja z g ++ daje następujący wynik
źródło
delete
pamięci ze stosu :)@ hop5 i @RnMss sugerują użycie lambd C ++ 11, ale jeśli masz do czynienia ze wskaźnikami, możesz użyć ich bezpośrednio:
wyjścia
Przepisana próbka z tej odpowiedzi będzie wtedy:
źródło
Niektórzy użytkownicy już udzielili odpowiedzi i wyjaśnili ją bardzo dobrze.
Chciałbym dodać jeszcze kilka rzeczy związanych z wątkiem.
Jak pracować z funktorem i wątkiem. Proszę odnieść się do poniższego przykładu.
Wątek utworzy własną kopię obiektu podczas przekazywania obiektu.
Innym sposobem osiągnięcia tego samego jest:
Ale jeśli chcesz przekazać obiekt przez referencję, użyj poniższej składni:
źródło