Передача ссылки на локальную переменную в main () другим потокам / функциям - плохая практика? - PullRequest
0 голосов
/ 21 марта 2020

Рассмотрим приведенный ниже пример, где я создаю локальную переменную specialNumber в main() и передаю ее по ссылке на новый поток, а также на другую функцию (не обращайте внимания на отсутствие блокировки / мьютекса):

#include <iostream>
#include <thread>

void threadRun(int& number) {
    while(true) {
        std::this_thread::sleep_for(std::chrono::seconds(2));
        std::cout << number << std::endl;
        number += 1;
    }
}

int main() {
    int specialNumber = 5;
    std::thread newThread(threadRun, std::ref(specialNumber));
    otherFunction(specialNumber);
    newThread.join();
}


void otherFunction(int& number) {
    // does something with number
}

Я знаю, что вообще следует избегать передачи ссылок на локальные переменные, так как после завершения функции переменная выйдет из области видимости, и ссылка станет недействительной.

Однако, поскольку переменная является локальной для main(), и эта функция не завершится, пока не завершится вся программа, есть ли что-то не так с этой практикой?

Мой конкретный c сценарий использования будет хранить здесь небольшой объект (в основном состоящий из указателей для кучи объектов вместе с вспомогательными функциями), который будет использоваться несколькими потоками и / или функциями, и передаваться по кругу. ссылка на это. Я знаю, что альтернативой является хранение его в куче с помощью умного указателя, такого как shared_ptr, но хранение такого маленького объекта таким способом мне кажется неэффективным.

Я прошу прощения, если какая-либо из моих терминов неверна Я довольно новичок в C ++. Пожалуйста, поправьте меня!

Ответы [ 2 ]

6 голосов
/ 21 марта 2020

Ваше предположение

Я знаю, что вообще следует избегать передачи ссылок на локальные переменные

кажется необоснованным.

В этом нет ничего плохого с передачей ссылок на функции. Однако функция, которая принимает ссылку на объект, не должна вступать во владение этим объектом. Функция не должна предполагать, что указанный объект продолжает жить после его выхода.

Это отличается от возврата ссылок на локальные переменные, что всегда неверно.

I не вижу проблем (не говоря уже о синхронизации) с передачей ссылок на потоки, и это, как правило, предпочтительнее альтернативы использованию глобальных переменных.

Умные указатели, такие как std::shared_ptr, требуются только в том случае, если функции должны принимать (общее) владение объектом, например, если threadRun хочет сохранить ссылку / указатель на объект после его выхода.

0 голосов
/ 21 марта 2020

Пока существует поток main, проблем не должно возникать, поскольку время жизни specialNumber контролируется им.

Однако я хочу подробнее остановиться на использовании std::ref(). Одним из вариантов использования std::ref() является именно тот сценарий, который вы кодируете.

Когда вы используете std::ref(), вы на самом деле возвращаете std::reference_wrapper, который можно скопировать. Оболочки ссылки могут храниться в контейнерах, тогда как обычные ссылки не могут.

Передача объектов по ссылке на конструктор потока является одним из способов, с помощью которого справочная обертка оказывается полезной, и std::ref() возвращает справочную обертку.

Если бы вы передали простую ссылку, вы бы увидели другое поведение.

Подробнее о std :: ref () и std :: reference_wrapper

Эта тема Чем полезно tr1 :: reference_wrapper? также полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...