I've a bit understanding about lvalue and rvalues. So as I know we cannot assign to an rvalue but non-const lvalue is ok.
#include <iostream>
#include <vector>
int main(){
std::vector<int> v{ 1, 2, 3, 4, 5 };
v.begin() = v.end() - 2;
std::cout << *v.begin() << std::endl; // 1
for (auto const& e : v)
std::cout << e << ", ";// 1, 2, 3, 4, 5,
std::cout << std::endl;
}
Why I can assign to begin()
but it does nothing on the elements?
v.begin()
is an iterator. Assigning to an iterator does not assign to the value the iterator points to. In addition, because v.begin()
is a prvalue, the object that you are assigning to gets destroyed at the end of the line, without affecting v
or any of the "permanent" memory it owns.
If v.begin()
were a raw pointer, the compiler would issue an error for trying to assign to an rvalue. However, the type std::vector<T>::iterator
is often a class type, and it seems that this is the case on your implementation (with the specific set of compiler flags you are using), so assigning to v.begin()
calls the operator=
of that class type. But that doesn't change the fact that the iterator object is a temporary object, and assigning to it has no further effects.
In order to assign to the element that v.begin()
points to, you need to dereference it: *v.begin() = *(v.end() - 2)
What is the result of assigning to std::vector::begin()?
The result of the assignment expression (the result is discarded in your example) is the assigned value. In this case the result is same as v.end() - 2
.
Note that since begin()
returns a value, this assignment only modifies the returned temporary object. The assignment doesn't modify the vector in any way. Given that the temporary object is discarded, the assignment has no observable effects in practice.
Futhermore, this assignment may be ill-formed if the standard library has chosen to implement std::vector::iterator
as a pointer.
Why I can assign to
begin()
Because
but it does nothing on the elements?
Because assigning an iterator doesn't modify the element that the iterator points at. Instead, the assignment changes what object the iterator is pointing at.
So as I know we cannot assign to an rvalue
This is not correct in general. In particular, it is not true for class types †.
† Unless the assignment operator of the class has lvalue-ref-qualifier (and has no rvalue-ref-qualified overload), which is unconventional.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With