【问题标题】:how std::thread constructor detects rvalue reference?std::thread 构造函数如何检测右值引用?
【发布时间】:2016-05-15 19:08:45
【问题描述】:

显然可以将右值引用传递给std::thread 构造函数。我的问题是在cppreference 中定义了这个构造函数。它说这个构造函数:

template< class Function, class... Args >
explicit thread( Function&& f, Args&&... args );

创建新的 std::thread 对象并将其与 执行。首先,构造函数复制/移动所有参数( 函数对象 f 和所有 args...) 到线程可访问的存储,就好像 按功能:

template <class T>
typename decay<T>::type decay_copy(T&& v) {
    return std::forward<T>(v);
}

据我所知:

std::is_same<int, std::decay<int&&>::type>::value

返回真。这意味着std::decay&lt;T&gt;::type 将删除参数的右值引用部分。那么std::thread 构造函数如何知道哪个参数是由左值或右值引用传递的呢?因为所有T&amp;T&amp;&amp;都会被std::decay&lt;T&gt;::type转换成T

【问题讨论】:

  • "对类型 T 应用左值到右值、数组到指针和函数到指针的隐式转换,删除 cv 限定符,并将结果类型定义为成员 typedef 类型" en.cppreference.com/w/cpp/types/decay - 你在哪里看到它删除了引用?
  • @xaxxon 你错过了::type
  • @T.C.删除了——但为什么它们是一样的?
  • @xaxxon 那是“左值到右值”部分。
  • 我明白了。不是右值会变成左值,而是 int 会变成 int&&

标签: c++ multithreading c++11 constructor perfect-forwarding


【解决方案1】:

std::thread 构造函数知道其参数的值类别,因为它知道 FunctionArgs... 是什么,它使用它们将其参数完美地转发到 decay_copy(或等效项)。

实际的线程函数不知道值的类别。它总是作为右值调用,带有所有右值参数 - 这是有道理的:fargs... 的副本是线程本地的,不会在其他任何地方使用。

【讨论】:

    【解决方案2】:
    auto s = std::decay_copy(std::string("hello"));
    

    相当于:

    template<>
    std::string std::decay_copy<std::string>(std::string&& src) {
        return std::string(std::move(src));
    }
    
    std::string s = decay_copy<std::string>(std::string("hello"));
    

    【讨论】:

    • @xaxxon 或多或少。它试图展示模板扩展的结果。
    【解决方案3】:

    完美转发的常见问题。如果要在函数中恢复有关右值的信息,则必须使用 std::forward std::forward 。如果您对值类型检测感兴趣,可以阅读此value_category。从描述中您可以找到编译器如何在编译时识别 rvalue、xvalue、lvalue、prvalue、gvalue 的信息。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 2023-03-31
      • 1970-01-01
      • 2014-01-29
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      相关资源
      最近更新 更多