Каким вызовом в стандартном C++ создаётся новый поток?

Ответ

В современном C++ (начиная с C++11) для создания потока используется конструктор класса std::thread из заголовочного файла <thread>.

Базовый синтаксис:

#include <thread>

std::thread thread_object(callable, arg1, arg2, ...);

Где callable — это функция, функциональный объект (лямбда, объект с operator()) или указатель на функцию-член класса. Поток начинает выполнение немедленно после создания.

Примеры:

  1. С обычной функцией:
    void print_message(const std::string& msg) {
        std::cout << msg << 'n';
    }
    int main() {
        std::thread t(print_message, "Hello from thread!");
        t.join(); // Важно: дождаться завершения перед выходом из main
        return 0;
    }
  2. С лямбда-выражением:
    std::thread t([]() {
        std::cout << "Lambda in threadn";
    });

Критически важные моменты:

  • Необходимо явно управлять жизненным циклом потока: вызвать либо join() (ожидание завершения), либо detach() (разрешить самостоятельное завершение). Если этого не сделать, деструктор std::thread вызовет std::terminate и аварийно завершит программу.
  • Для передачи аргументов по ссылке нужно использовать std::ref() или std::cref().
  • Потоки нельзя копировать, но можно перемещать (std::move).

Ответ 18+ 🔞

О, смотри-ка, какой у нас тут учебник по потокам. Ну что ж, давай разберём эту магию, пока не наступила хиросима в твоём коде.

Вот смотри, в современном плюсах, начиная с одиннадцатой версии, появилась такая штука — std::thread. Берёшь её, как бутерброд с колбасой, и намазываешь на неё любую выполняемую хуйню. Функцию, лямбду, или даже метод какого-нибудь класса. Главное — правильно подать.

Как это выглядит в коде, ёпта:

#include <thread>

std::thread thread_object(вызываемая_хуйня, аргумент1, аргумент2, ...);

Создал объект — и всё, поток уже побежал, как угорелый, делать свою работу. Волнение ебать, правда?

Вот тебе пара живых примеров, чтобы не бздеть:

  1. Старая добрая функция:
    void print_message(const std::string& msg) {
        std::cout << msg << 'n';
    }
    int main() {
        std::thread t(print_message, "Привет из потока, чувак!");
        t.join(); // А вот это ОЧЕНЬ важно! Без этого будет пиздец.
        return 0;
    }
  2. Модная лямбда (все теперь такие умные):
    std::thread t([]() {
        std::cout << "Лямбда в потоке, красота!n";
    });

А теперь слушай сюда, это критично, как вилка в глаз:

  • Управляй своей сракой! Ты создал поток — ты за него и отвечаешь. Либо ты говоришь join() и терпеливо ждёшь, пока он всё сделает (терпения ноль ебать, но надо). Либо кричишь detach() и отпускаешь его в свободное плавание, как утёнка. Если ты просто создашь поток и наебёшь — деструктор std::thread вызовет std::terminate, и твоя программа накроется медным тазом. Сам от себя охуеешь, когда это произойдёт.
  • Хочешь передать что-то по ссылке? Оберни в std::ref() или std::cref(), а то передашь копию и будешь потом думать, почему ничего не меняется. Э, бошка, думай!
  • Потоки — штука одноразовая. Скопировать нельзя, это как залупа конская. Но можно переместить с помощью std::move, если очень хочется передать кому-то управление.

Вот и вся наука. Главное — не распиздяйничай с join/detach, а то будет тебе нигерсраки вместо многопоточности.