[英]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.