【问题标题】:Is it safe to pass arguments by reference into a std::thread function?通过引用将参数传递给 std::thread 函数是否安全?
【发布时间】:2017-05-19 12:23:03
【问题描述】:
#include <thread>
#include <string>
#include <vector>
#include <chrono>

using namespace std;

void f(const vector<string>& coll)
{
    this_thread::sleep_for(1h);

    //
    // Is coll guaranteed to be valid before exiting this function?
    //
}

int main()
{
    {
        vector<string> coll(1024 * 1024 * 100);
        thread(f, coll).detach();
    }

    //
    // I know std::thread will copy arguments into itself by default, 
    // but I don't know whether these copied objects are still valid
    // after the std::thread object has been destroyed.
    //

    while (true);
}

通过引用将参数传递给 std::thread 函数是否安全?

【问题讨论】:

  • 简短回答:是的,完全安全且没问题。
  • 你没有通过对线程的引用传递任何东西。
  • 我很抱歉,你是对的;我看错了代码。
  • @TC,我知道std::thread默认会将参数复制到自己中,但我不知道这些复制的对象在std::thread对象被销毁后是否仍然有效。
  • std::thread 对象不再与执行线程相关联,因为您来自它的detachthread 本身会在调用f 时移动vector,这将绑定到vector const&amp; 参数,并且它的生命周期将在f 退出时结束,因此您的代码是安全的。

标签: c++ multithreading c++11 standards object-lifetime


【解决方案1】:
  • coll在退出这个函数之前是否保证有效?

    • 更新:是的。当您将coll 传递给main 函数中std::thread 的构造函数时,因为coll 是一个对象,所以它被decay 复制。这个decay 本质上复制了moves 向量(因此它变成了右值),它将在线程执行期间绑定到f 中的coll 参数。 (感谢@Praetorian 的评论)
  • 通过引用将参数传递给std::thread 函数是否安全?

    • 您的参数是 decay 复制的,因此您实际上从未通过引用 std::thread 传递任何内容。
  • 参考std::decayhttp://www.cplusplus.com/reference/type_traits/decay/

  • 在这个问题std::thread with movable, non-copyable argument 中接受的答案解释了传递给std::thread 的参数会发生什么情况

【讨论】:

  • 你能详细说明“decay复制”是什么意思吗?如果它不是通过引用传递的,那么副本是在哪里/何时制作的?显然,在 OP 的示例中,必须将副本的引用传递给 f。还可能值得注意的是,lambda 仍然允许通过引用进行捕获,而不会遇到这种衰减行为。
【解决方案2】:

正如@T.C. 的评论,你没有传递对线程的引用,你只是在线程中复制了一个向量:

thread(f, coll).detach(); // It's NOT pass by reference, but makes a copy.

如果你真的想通过引用传递,你应该这样写:

thread(f, std::ref(coll)).detach(); // Use std::ref to pass by reference

如果线程试图访问向量,那么代码将出现段错误,因为当线程运行时,向量很可能已经被破坏(因为它超出了主程序的范围)。

所以你的问题:

通过引用将参数传递给std::thread 函数是否安全?

  • 如果您确定对象在线程运行期间保持有效,则它是安全的;
  • 如果对象被破坏是不安全的,你会得到段错误。

【讨论】:

  • 新人的明确答案。谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-07-16
  • 2021-11-07
  • 1970-01-01
  • 1970-01-01
  • 2013-11-29
  • 2016-03-13
  • 2017-06-05
  • 2014-01-29
相关资源
最近更新 更多