#c
#c
Вопрос:
Я читаю главу 15 (параллелизм) в книге Бьярне Страуструпа «A Tour of C «. Я не понимаю его вводный пример в разделе 15.2 (он ссылается на раздел 6.3.2, который, похоже, не ответил на мой вопрос). Следующий фактически компилируемый код возникает из моих попыток понять его:
#include <iostream>
#include <thread>
using namespace std;
struct F {
void operator()();
};
void F::operator()()
{
cout << "Hello" << endl;
}
void f()
{
cout << "Hello" << endl;
}
int main()
{
thread t1 { F() };
thread t2 { f };
thread t3(f);
//thread t4(F()); (does not work)
t1.join();
t2.join();
t3.join();
}
У меня есть два вопроса по этому поводу:
- Что
thread t1 { F() };
делает? Я не могу написать то же самое с f вместо F (я не ожидал, что это сработает). Также у меня была теория, что, возможно, F() — это своего рода указатель на функцию F::operator() сnullptr
переданным ему a или чем-то еще, но и это не работает:
void (a*)() = F();
Итак, что делает F() в этом контексте?
- Почему я могу создать этот поток с фигурным инициализатором, а не с круглыми скобками?
Комментарии:
1. F() — это вызов конструктора, поэтому при этом создается новый объект F.
2.
thread t4(F());
объявляет функцию t4, которая возвращает объект типа thread и принимает аргумент типа функции, которая возвращает F.3. Спасибо! Сейчас я действительно чувствую себя глупо из-за того, что не понял, что F() — это конструктор. 🙂
4. Кстати, в книге есть комментарий: «F()() выполняется в отдельном потоке …» Итак, это оператор вызова экземпляра F, созданного с помощью F() , теперь все имеет смысл…
5. На самом деле это не «вызов конструктора»; для этого в C нет такого синтаксиса, хотя он выглядит как один. Вы «объявляете» временную переменную (вроде). Но это слишком придирчиво.
Ответ №1:
Из ссылки на std::thread вы вызываете следующий конструктор для t1
, t2
, и t3
:
template <class Function, class... Args>
explicit thread( Functionamp;amp; f, Argsamp;amp;... args);
где
f
— Вызываемый объект для выполнения в новом потоке
t1
создается из объекта типа с прямой инициализацией F
. Поскольку F
имеет an operator()
, это вызываемый объект, и поэтому объявление работает.
Конечно, f
это функция, так что это определенно вызываемая вещь, и поэтому объявление t2
также работает. t3
аналогично t2
, с той лишь разницей, что t3
он инициализируется прямым способом, тогда t2
как инициализируется фигурными скобками.
t4
не работает, потому что на самом деле это вообще не объявление потока. Это пример досадного синтаксического анализа. t4
на самом деле это объявление функции, где функция возвращает a thread
, а сама принимает функцию, которая не принимает аргументов, и возвращает an F
.