Запустить поток с функцией-членом
Я пытаюсь построить std::thread С функцией-членом, которая не принимает аргументов и возвращает void. Я не могу понять, какой синтаксис работает - компилятор жалуется, несмотря ни на что. Как правильно реализовать spawn() Так что он возвращает std::thread выполняет test()?
#include <thread>
class blub {
void test() {
}
public:
std::thread spawn() {
return { test };
}
};
5 ответов:
#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(); }изменить: Бухгалтерия вашего редактирования, вы должны сделать это так:
std::thread spawn() { return std::thread(&blub::test, this); }
обновление: я хочу объяснить еще несколько моментов, некоторые из них также обсуждались в комментариях.
синтаксис, описанный выше, определяется в терминах определения INVOKE (§20.8.2.1):
определить INVOKE (f, t1, t2,..., Теннесси) следующим образом:
- (t1.*f) (t2, ..., tN) когда f-указатель на элемент функция класса T и t1-это объект типа T или ссылка на объект типа T. тип T или ссылка на объект типа, производного от T;
- ((*t1).*f) (t2, ..., tN) когда f является указателем на функцию-член класса T и t1 не является одним из типов, описанных в предыдущем разделе товар;
- t1.*f, когда N == 1 и f-указатель на данные-члены класса T, а t 1-объект типа T или a
ссылка на объект типа T или ссылка на объект a
тип, производный от T;- (*t1).*f, когда N == 1 и f является указателем на данные-члены класса T и t 1 не является одним из типов, описанных в предыдущем пункте;
- f(t1, t2,..., TN) во всех остальных случаях.
еще один общий факт, который я хочу отметить, заключается в том, что по умолчанию конструктор потока будет копировать все аргументы, переданные ему. Причина этого в том, что аргументы, возможно, придется пережить вызывающий поток, копирование аргументов гарантирует это. Вместо этого, если вы хотите действительно передать ссылку, вы можете использовать
std::reference_wrapperсозданоstd::ref.std::thread (foo, std::ref(arg1));делая это, вы обещаете, что вы позаботитесь о том, чтобы гарантировать, что аргументы все еще будут существовать, когда поток работает на них.
обратите внимание, что все вещи, упомянутые выше, также могут быть применены к
std::asyncиstd::bind.
так как вы используете C++11, лямбда-выражение является хорошим и чистым решением.
class blub { void test() {} public: std::thread spawn() { return std::thread( [this] { this->test(); } ); } };С
this->можно опустить, это может быть сокращено до:std::thread( [this] { test(); } )или просто
std::thread( [=] { test(); } )
вот пример
#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; }компиляция с g++ дает следующий результат
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 и @RnMss предложили использовать лямбды C++11, но если вы имеете дело с указателями, вы можете использовать их напрямую:
#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; }выходы
2переписать образец от ответ тут:
#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; }
некоторые пользователи уже дали свой ответ и очень хорошо объяснил.
Я хотел бы добавить несколько вещей, связанных с нить.
как работать с функтором и резьбы. Пожалуйста, обратитесь к приведенному ниже примеру.
поток сделает свою собственную копию объекта при передаче объекта.
#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(); }другой способ достижения того же самого например:
void main() { thread t((CB())); t.join(); }но если вы хотите передать объект по ссылке, то используйте следующий синтаксис:
void main() { CB obj; //thread t(obj); thread t(std::ref(obj)); t.join(); }
Comments