Why in this code the compiler chooses the r-value ref version

Take this simplified example:

std::vector< int > v; v.push_back( 1 ); v.insert( v.end()-1, v[ v.size()-1 ] ); // the problem is on this line // We output the vector std::for_each( v.begin(), v.end(), []( const int& e_ ){ std::cout<<e_<<std::endl; } ); 

output:

 -17891602 1 

The author of the code, designed to insert a duplicate of the last element before the end of the vector. There are some good ways to do this, but the author decided to use this one.

It worked as "expected" before C ++ 11. This is due to the fact that in the microsoft implementation of the insert in the vector they make a copy of the value for the insert if the inserted value is in the range of the vector.

Now with C ++ 11 there is a version of the insert that uses the r-value reference, which does not need this trick, because it is temporary.

But it is surprising that, using the above code, the compiler decides to take the version of the r-value ref value instead of the version for the link, which inserts an uninitialized value before the end of the vector. Note that the [] operator is returned by reference.

Why did the compiler decide to take the version using the r-value link?

+1
source share
2 answers

It turns out that this is a problem with the VS 2010 compiler, which was fixed with the 2013 compiler. I don't know which of these two versions is accurate, but it calls the reference version of r-value using VS2010 SP1 and the version with l-value with VS2013 Update 3, which is the expected behavior.

As you can see in the comments above, some people tested the code using other compilers than Microsoft compilers, and it also works as expected.

EDIT: I found another post about the same issue. Is this a combination of patterns, const & and & &: Visual C ++ 2010, rvalue link error?

0
source

It looks like you might have a bug, either in the implementation of vector , or in your own code. However, I see no error in what you posted. Here is a complete example of your post:

 #include <iostream> #include <vector> template <class Iter> void display(Iter first, Iter last) { std::cout << "{"; if (first != last) { std::cout << *first; for (++first; first != last; ++first) std::cout << ", " << *first; } std::cout << "}\n"; } template <class C> void display(const C& c) { display(c.begin(), c.end()); } int main() { std::vector< int > v; v.push_back( 1 ); v.insert( v.end()-1, v[ v.size()-1 ] ); display(v); } 

which for me outputs:

 {1, 1} 

That is, in the implementation that I use (lib ++), the lvalue insert overload is selected.

+4
source

Source: https://habr.com/ru/post/1340276/


All Articles