Доступ к перемещенному std::string в новом потоке

Рассмотрим случай ниже

Строка имени перемещается в качестве аргумента в поток.

 void start(std::string&& name) {
        t = std::thread{&ThreadRunner::run, this, std::forward<std::string>(name)};
    }

Функция запуска потока также принимает ссылку rvalue.

 void run(std::string&& name) {
        const auto errnum = pthread_setname_np(t.native_handle(), name.c_str());
        if (errnum != 0) {
            std::cout << "ERROR " << std::endl;
        }
    }

Поток создается с помощью функции запуска, как показано ниже:

  ThreadRunner r;
  r.start(std::string("somename"));

Вопрос в том. Возможно ли, что std::string, к которому обращаются в functionrun через pthread_setname_np, может быть ненужным, потому что временное вышло из области действия, когда ее область действия закончилась?

Демонстрация В приведенной выше демонстрации после завершения call гарантируется, что строка somename допустима в функции run?

Изменить: Демонстрация с конструкторами/деструкторами Строка std::string в вопросе теперь заменена на Wrap для выведите задействованные конструкторы.

Результат: (второе поле — адрес объекта, третье — идентификатор потока)

Constructed 0x7ffc395e0ef0 140605000369984
Move Constructed 0x7ffc395e0e60 140605000369984
Move Constructed 0x177a0a0 140605000369984
Destroyed 0x7ffc395e0e60 140605000369984
Destroyed 0x7ffc395e0ef0 140605000369984
Call ended

somename
Destroyed 0x177a0a0 140604983461632

Последний объект уничтожается после окончания run. Это все еще относится к временным. Думаю, нет.

Более чистый пример

Изменить: после комментариев вопрос сводится к

"После того, как первоначальный вызов void start(std::string&& name); вернулся и после завершения конструктора std::thread, где находится строка, над которой работает void run(std::string&& name);?"

Последний демонстрационный код показывает, что объект Wrap, на который ссылается run, уничтожается после выхода run.


person themagicalyang    schedule 26.04.2017    source источник
comment
Вместо того, чтобы злоупотреблять std::forward работой, для которой он не предназначен, используйте std::move.   -  person Rakete1111    schedule 26.04.2017
comment
@ Rakete1111 Принято к сведению. Спасибо.   -  person themagicalyang    schedule 26.04.2017


Ответы (2)



Висячих ссылок нет, потому что аргументы конструктора std::thread копируются/перемещаются в некоторую структуру клиентским потоком. Затем вновь созданный поток будет выполняться на скопированных/перемещенных объектах в этой структуре.

В вашем конкретном случае объект std::string действительно перемещается в описанную структуру. Это std::string объект, над которым работает run(). Он будет должным образом уничтожен, когда поток завершит свое выполнение.

person Ralph Tandetzky    schedule 28.04.2017