Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the result of assigning to std::vector<T>::begin()?

Tags:

c++

vector

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?

like image 837
Syfu_H Avatar asked Nov 28 '22 00:11

Syfu_H


2 Answers

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)

like image 95
Brian Bi Avatar answered Dec 09 '22 14:12

Brian Bi


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

  1. Iterators are assignable.
  2. Rvalues of class type can be assigned .
  3. The iterator happens to be a class type.

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.

like image 28
eerorika Avatar answered Dec 09 '22 16:12

eerorika