Параллельное программирование на С++ в действии. Практика разработки многопоточных программ | страница 28
>edit_document
), передав ей в качестве аргумента имя только что выбранного файла.Этот пример демонстрирует также, почему бывает полезно передавать аргументы функции потока: мы передаем конструктору объекта >std::thread
не только имя функции (1), но и её параметр — имя файла. Существуют другие способы добиться той же цели, например, использовать не обычную функцию с параметрами, а объект-функцию с данными-членами, но библиотека предлагает и такой простой механизм.
2.2. Передача аргументов функции потока
Из листинга 2.4 видно, что по существу передача аргументов вызываемому объекту или функции сводится просто к передаче дополнительных аргументов конструктору >std::thread
. Однако важно иметь в виду, что по умолчанию эти аргументы копируются в память объекта, где они доступны вновь созданному потоку, причем так происходит даже в том случае, когда функция ожидает на месте соответствующего параметра ссылку. Вот простой пример:
>void f(int i, std::string const& s);
>std::thread t(f, 3, "hello");
Здесь создается новый ассоциированный с объектом >t
поток, в котором вызывается функция >f(3, "hello")
. Отметим, что функция >f
принимает в качестве второго параметра объект типа >std::string
, но мы передаем строковый литерал >char const*
, который преобразуется к типу >std::string
уже в контексте нового потока. Это особенно важно, когда переданный аргумент является указателем на автоматическую переменную, как в примере ниже:
>void f(int i, std::string const& s);
>void oops(int some_param) {
> char buffer[1024]; ←
(1)
> sprintf(buffer, "%i", some_param);
> std::thread t(f, 3, buffer); ←
(2)
> t.detach();
>}
В данном случае в новый поток передается (2) указатель на локальную переменную >buffer
(1), и есть все шансы, что выход из функции oops произойдет раньше, чем буфер будет преобразован к типу >std::string
в новом потоке. В таком случае мы получим неопределенное поведение. Решение заключается в том, чтобы выполнить преобразование в >std::string
до передачи >buffer
конструктору >std::thread
:
>void f(int i,std::string const& s);
>void not_oops(int some_param) {
> char buffer[1024]; │
Использование
> sprintf(buffer, "%i", some_param); │
std::string
> std::thread t(f, 3, std::string(buffer)); ←┘
позволяет избежать
> t.detach();