簡體   English   中英

C++:為什么我們可以將函數返回的向量中的元素綁定到非常量左值引用?

[英]C++: Why can we bind elements in a vector returned by a function to non-const lvalue references?

我是移動語義的新手,想了解這段代碼中發生的事情:

vector<int> create_vector() {
    return {0, 1, 2};
}

for (int &x : create_vector()) {
    /* ... */         
}

如果我理解正確,函數調用create_vector()返回一個右值。 因此,其中的元素也應該是右值(即 0、1、2 是右值)。 但是,在 for 循環范圍內,我們將這些右值綁定到一個非常量左值引用int &x ,這是不允許的嗎? 我認為非常量左值引用只能綁定到左值,而不是右值。

這里發生了什么事? 為什么這是允許的?

您正在返回帶有右值的 Container,但是在對向量調用::begin()然后在返回的迭代器上調用operator*()之后返回了各個元素,返回的迭代器返回一個引用,如下所示:

      // Forward iterator requirements
      _GLIBCXX20_CONSTEXPR
      reference
      operator*() const _GLIBCXX_NOEXCEPT
      { return *_M_current; }

如果您在cppinsights.io中編寫 for 循環,那么您會看到 for 循環正在調用.begin然后它正在調用operator*()

#include <vector>
using namespace std;

int foo() {
  int res;
  for (auto& val : vector<int>{}) {
    res += val;
  }
  return res;
}

這是從上面的示例生成此鏈接的鏈接

#include <vector>
using namespace std;

int foo()
{
  int res;
  {
    std::vector<int, std::allocator<int> > && __range1 = std::vector<int, std::allocator<int> >{};
    __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > __begin1 = __range1.begin();
    __gnu_cxx::__normal_iterator<int *, std::vector<int, std::allocator<int> > > __end1 = __range1.end();
    for(; !__gnu_cxx::operator==(__begin1, __end1); __begin1.operator++()) {
      int & val = __begin1.operator*();
      res = res + val;
    }
    
  }
  return res;
}

這是vector::begin on cppreference 這是一個指向itrator_traits的鏈接,它可以用來獲取向量迭代器的引用/指針類型,如下所示:

using your_vector = std::vector<int>;
using vector_iterator = typename your_vector::iterator;
using traits = std::iterator_traits<vector_iterator>;
using reference_type = typename traits::reference;
using pointer_type = typename traits::pointer;

有更簡單的方法來獲取這些類型,但這是標准容器的通用方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM