Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

when would you change std::vector::end() directly?

Tags:

c++

According to c++ reference, vector::end() is declared as iterator end() noexcept; (1st form).

Does it mean we can manipulate it directly like below?

vector<int> v(10);
v.end() = v.begin()+100; // change its end iterator arbitrarily

This compiles fine in clang but I suspect that this would cause run-time issues. segmentation fault? memory leak? I don't know.

My questions are:

  1. Is it going to cause run-time issues?
  2. Is exposing this for arbitrary manipulation a defect in the design in the first place?
  3. Is there any meaningful use case of directly manipulate the end() iterator which does not cause any run-time issue?
like image 630
james Avatar asked Nov 05 '19 11:11

james


3 Answers

  1. Is it going to cause run-time issues?

No. std::vector::end() returns by value. So v.end() = v.begin()+100; just assign to the copied temporary iterator returned by v.end(). (Precisely the copy assignment operator is called on the temporary, which is only possible for class types.) The temporary is destroyed immediately and the assignment has nothing to do with the vector v.

  1. Is exposing this for arbitrary manipulation a defect in the design in the first place?

It's just, meaningless.

  1. Is there any meaningful use case of directly manipulate the end() iterator which does not cause any run-time issue?

The end iterator is controlled by the vector itself, you can't change it directly. It gets changed by performing modification on the vector like push_back, erase, etc.

like image 69
songyuanyao Avatar answered Nov 16 '22 14:11

songyuanyao


vector.end() returns an iterator by value. That's entirely normal in C++. You can modify the returned value, but you have to understand that the value is a copy. Changing the copy doesn't change the original.

Does it make sense to modify such a temporary value? Certainly. *--(v.end()) is an example. That doesn't change v.end() but it decrements the returned iterator before dereferencing that copy. That's good because you can't dereference v.end() itself. *--(v.end()) is already v.back()

like image 38
MSalters Avatar answered Nov 16 '22 13:11

MSalters


In addition to the existing answers pointing out that the assignment is a no-op; it is also not portable!

std::vector<SomeType> v(10);

v.end() = v.begin() + 100;

This might compile when your standard library vendor implements std::vector::iterator as a custom class type. But v.end() might also return a raw pointer, as raw pointers qualify as iterators. And as you can't assign a rvalue raw pointer, the compiler might refuse the above.

like image 2
lubgr Avatar answered Nov 16 '22 14:11

lubgr