c++ Insight

首先,用c++ insight看看loop based loop这个语法糖究竟做了什么 ​

//original
int func() {
    std::map<int,int> a;
    for(auto&& [k,v]:a){
      int d = k+v;
    }
    return 0;
}
//generated by c++ insight
int func()
{
  std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > > a = std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > >();
  {
    std::map<int, int, std::less<int>, std::allocator<std::pair<const int, int> > > & __range1 = a;
    std::_Rb_tree_iterator<std::pair<const int, int> > __begin1 = __range1.begin();
    std::_Rb_tree_iterator<std::pair<const int, int> > __end1 = __range1.end();
    for(; !operator==(__begin1, __end1); __begin1.operator++()) {
      std::pair<const int, int> & __operator12 = __begin1.operator*();
      const int & k = std::get<0UL>(__operator12);
      int & v = std::get<1UL>(__operator12);
      int d = k + v;
    }
    
  }
  return 0;
}

可以看到range based loop在语法层面,就是简单的遍历迭代器。注意其中获得元素使用的是__begin1.operator*()

universal reference

effective modern c++的item24是:区分右值引用和通用引用(universal reference)

一般来说,如果我们直接使用变量类型+&&,这样子表示的右值引用

右值引用只可以绑定右值,不可以绑定左值

而如果是类似T&&的形式,且T是需要进行模板匹配的,那么表示的就不是右值引用,而是通用引用。

通用引用基本上什么都可以绑定(pretty much any),左值,右值,const,volatile通杀,所以一般用来做模板函数里面的参数转发用的比较多

除了转发会用到,auto&&也是一个通用引用。通用引用的具体类型取决于给他初始化时候用的是左值还是右值。

通过c++ insight可以看到初始化时通过__begin1.operator*(),一般来说是左值引用。

因此只要__begin1.operator*()返回左值引用,range based loop中使用auto&auto&&是没区别的,都是表示左值引用。

我之前之所以迷惑,就是把这里的&&当作了右值引用。实际上这里是通用引用。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注