33

考虑:

std::tuple<int , const A&> func (const A& a) 
{
  return std::make_tuple( 0 , std::ref(a) );
}

是否std::ref需要编写正确且可移植的代码?(没有它编译很好)

背景:

如果我删除std::ref我的代码构建良好,没有任何警告(g++-4.6 -Wall),但不能正确运行。

如果感兴趣,定义A

struct A {
  std::array<int,2> vec;
  typedef int type_t;

  template<typename... OPs,typename... VALs>
  A& operator=(const std::pair< std::tuple<VALs...> , std::tuple<OPs...> >& e) {
    for( int i = 0 ; i < vec.size() ; ++i ) {
      vec[i] = eval( extract(i,e.first) , e.second );
    }
  }
};
4

4 回答 4

27

std::ref必要的示例之一:

void update(int &data)  //expects a reference to int
{
    data = 15;
}
int main()
{
    int data = 10;

    // This doesn't compile as the data value is copied when its reference is expected.
    //std::thread t1(update, data);         

    std::thread t1(update, std::ref(data));  // works

    t1.join();
    return 0;
}

构造std::thread函数复制提供的值,而不转换为预期的参数类型(在本例中为引用update()类型,请参阅 参考资料)。所以我们需要将真正需要引用的参数包装std::ref.

于 2017-08-22T17:19:22.063 回答
19

std::ref不做参考,所以在你的代码示例中它没有做你所期望的。std::ref创建一个行为类似于引用的对象。例如,当您想要实例化一个仿函数并将其类似引用的版本传递给标准库算法时,它可能很有用。由于算法按值获取函子,因此您可以使用std::ref来包装函子。

于 2012-08-06T17:35:21.110 回答
18
  • make_tuple(0, a)做一个tuple<int, A>.
  • make_tuple(0, ref(a))做一个tuple<int, reference_wrapper<A>>.
  • 你也可以说tuple<int, A&> t(0, a);你不能用make_tuple或使用的元组std::tie
于 2012-08-06T17:32:34.637 回答
0

回答标题 ( When is the use of std::ref necessary?) 中的问题:另一种std::ref有用的情况是循环遍历对象引用列表并修改它们:

std::vector<int> v1, v2;
  
void test() {
  for (std::vector<int>& vv : 
    // Compiles
    { std::ref(v1), std::ref(v2) } 
  
    // Compiler rejects this with:
    //   binding reference of type 'vector<...>' to value of 
    //   type 'const vector<...>' drops 'const' qualifier 
    // { v1, v2} 
  ) {
      vv.push_back(3);
  }
}

如果不在std::ref列表中使用,对象将被视为const并且不能修改(另请参见https://godbolt.org/z/Ta6YM31KM)。

于 2021-12-23T11:04:28.997 回答