
abergmeier
Ich versuche, eine zu konstruieren std::thread
mit einer Member-Funktion, die keine Argumente akzeptiert und zurückgibt void
. Ich kann keine Syntax herausfinden, die funktioniert – der Compiler beschwert sich, egal was passiert. Was ist die richtige Art der Umsetzung spawn()
damit es a zurückgibt std::thread
das ausführt test()
?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};

Stefan Dollberg
#include <thread>
#include <iostream>
class bar {
public:
void foo() {
std::cout << "hello from member function" << std::endl;
}
};
int main()
{
std::thread t(&bar::foo, bar());
t.join();
}
BEARBEITEN: Um Ihre Bearbeitung zu berücksichtigen, müssen Sie dies folgendermaßen tun:
std::thread spawn() {
return std::thread(&blub::test, this);
}
AKTUALISIEREN: Ich möchte noch einige Punkte erläutern, einige davon wurden auch in den Kommentaren diskutiert.
Die oben beschriebene Syntax ist in Bezug auf die INVOKE-Definition (§20.8.2.1) definiert:
Definieren Sie INVOKE (f, t1, t2, …, tN) wie folgt:
- (t1.*f)(t2, …, tN) wenn f ein Zeiger auf eine Elementfunktion einer Klasse T ist und t1 ein Objekt vom Typ T oder eine Referenz auf ein Objekt vom Typ T oder eine Referenz auf an ist Objekt eines von T abgeleiteten Typs;
- ((*t1).*f)(t2, …, tN) wenn f ein Zeiger auf eine Elementfunktion einer Klasse T ist und t1 keiner der im vorherigen Punkt beschriebenen Typen ist;
- t1.*f wenn N == 1 und f ein Zeiger auf Elementdaten einer Klasse T ist und t 1 ein Objekt vom Typ T oder a ist
Referenz auf ein Objekt vom Typ T oder eine Referenz auf ein Objekt von a
Typ abgeleitet von T;
- (*t1).*f wenn N == 1 und f ein Zeiger auf Mitgliedsdaten einer Klasse T ist und t 1 keiner der im vorherigen Punkt beschriebenen Typen ist;
- f(t1, t2, …, tN) in allen anderen Fällen.
Eine weitere allgemeine Tatsache, auf die ich hinweisen möchte, ist, dass der Thread-Konstruktor standardmäßig alle ihm übergebenen Argumente kopiert. Der Grund dafür ist, dass die Argumente möglicherweise den aufrufenden Thread überleben müssen, das Kopieren der Argumente garantiert dies. Wenn Sie stattdessen wirklich eine Referenz übergeben möchten, können Sie a verwenden std::reference_wrapper
erstellt von std::ref
.
std::thread (foo, std::ref(arg1));
Indem Sie dies tun, versprechen Sie, dafür zu sorgen, dass die Argumente noch vorhanden sind, wenn der Thread mit ihnen arbeitet.
Beachten Sie, dass alle oben genannten Dinge auch angewendet werden können std::async
und std::bind
.

RnMss
Da Sie C++11 verwenden, ist Lambda-Ausdruck eine schöne und saubere Lösung.
class blub {
void test() {}
public:
std::thread spawn() {
return std::thread( [this] { this->test(); } );
}
};
seit this->
kann weggelassen werden, es könnte verkürzt werden zu:
std::thread( [this] { test(); } )
oder nur (veraltet)
std::thread( [=] { test(); } )
Hier ist ein vollständiges Beispiel
#include <thread>
#include <iostream>
class Wrapper {
public:
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
std::thread member1Thread() {
return std::thread([=] { member1(); });
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread([=] { member2(arg1, arg2); });
}
};
int main(int argc, char **argv) {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
std::thread tw2 = w->member2Thread("hello", 100);
tw1.join();
tw2.join();
return 0;
}
Das Kompilieren mit g++ führt zu folgendem Ergebnis
g++ -Wall -std=c++11 hello.cc -o hello -pthread
i am member1
i am member2 and my first arg is (hello) and second arg is (100)
@hop5 und @RnMss schlugen vor, C++11-Lambdas zu verwenden, aber wenn Sie sich mit Zeigern befassen, können Sie sie direkt verwenden:
#include <thread>
#include <iostream>
class CFoo {
public:
int m_i = 0;
void bar() {
++m_i;
}
};
int main() {
CFoo foo;
std::thread t1(&CFoo::bar, &foo);
t1.join();
std::thread t2(&CFoo::bar, &foo);
t2.join();
std::cout << foo.m_i << std::endl;
return 0;
}
Ausgänge
2
Umgeschriebenes Beispiel aus dieser Antwort wäre dann:
#include <thread>
#include <iostream>
class Wrapper {
public:
void member1() {
std::cout << "i am member1" << std::endl;
}
void member2(const char *arg1, unsigned arg2) {
std::cout << "i am member2 and my first arg is (" << arg1 << ") and second arg is (" << arg2 << ")" << std::endl;
}
std::thread member1Thread() {
return std::thread(&Wrapper::member1, this);
}
std::thread member2Thread(const char *arg1, unsigned arg2) {
return std::thread(&Wrapper::member2, this, arg1, arg2);
}
};
int main() {
Wrapper *w = new Wrapper();
std::thread tw1 = w->member1Thread();
tw1.join();
std::thread tw2 = w->member2Thread("hello", 100);
tw2.join();
return 0;
}
Einige User haben bereits ihre Antwort gegeben und sehr gut erklärt.
Ich möchte noch ein paar Dinge hinzufügen, die sich auf Threads beziehen.
-
Wie man mit Funktor und Thread arbeitet. Bitte beachten Sie das folgende Beispiel.
-
Der Thread erstellt beim Übergeben des Objekts eine eigene Kopie des Objekts.
#include<thread>
#include<Windows.h>
#include<iostream>
using namespace std;
class CB
{
public:
CB()
{
cout << "this=" << this << endl;
}
void operator()();
};
void CB::operator()()
{
cout << "this=" << this << endl;
for (int i = 0; i < 5; i++)
{
cout << "CB()=" << i << endl;
Sleep(1000);
}
}
void main()
{
CB obj; // please note the address of obj.
thread t(obj); // here obj will be passed by value
//i.e. thread will make it own local copy of it.
// we can confirm it by matching the address of
//object printed in the constructor
// and address of the obj printed in the function
t.join();
}
Eine andere Möglichkeit, dasselbe zu erreichen, ist wie folgt:
void main()
{
thread t((CB()));
t.join();
}
Wenn Sie das Objekt jedoch als Referenz übergeben möchten, verwenden Sie die folgende Syntax:
void main()
{
CB obj;
//thread t(obj);
thread t(std::ref(obj));
t.join();
}
10024000cookie-checkThread mit Member-Funktion startenyes
Meinst du, die Funktion gibt void zurück, wird void genannt, oder sie hat einfach keine Parameter. Kannst du den Code für das hinzufügen, was du zu tun versuchst?
– Zaid Amir
20. Mai 2012 um 13:02 Uhr
Hast du getestet? (Habe ich noch nicht.) Ihr Code scheint sich auf RVO (Return-Value-Optimzation) zu verlassen, aber ich glaube nicht, dass Sie dies tun sollten. Ich denke, mit
std::move( std::thread(func) );
ist besser, zstd::thread
hat keinen Kopierkonstruktor.– RnMss
10. Oktober 2013 um 11:28 Uhr
@RnMss: Sie können sich auf RVO verlassen und verwenden
std::move
ist in diesem Fall überflüssig – wäre dies nicht der Fall und gäbe es keinen Kopierkonstruktor, würde der Compiler sowieso einen Fehler ausgeben.– Qualia
22. Oktober 2015 um 13:19 Uhr