   std::vector
  This proposition was made in C++ Templates : the complete guide. Note that pop_back() of a vector removes the last element but doesn't return it. The reason for this behavior is exception safety. It is impossible to implement a completely exception-safe version of pop() that returns the removed element It might be naive to ask, but can someone explain why this is.   
  Just guessing but maybe because it could have to allocate memory to copy the object and then return it.  Memory allocation could fail.For simple types (such as int) it wouldn't need to allocate memory but if you had a struct or class, it would have to.   ;  Top return the value pop has to look like this pseudo code:T std::vector<T>::pop_back(){  --end;  T item = items[end];  ~items[end];  return item; }//......try{  T last_item = my_vector.pop_back();}catch{}The implementation of std::vector can't make any assumptions about what item "T" is or does. All std::vector knows is that "T" implements a specific set of operators.The second line copy constructs the element. This could throw an exception. Notice that constructors do not return values.Third line destructs the element. This could also throw an exception. Notices that destructors have no return.Now notice, that if the copy constructor throws, you want the exception to travel out of std::vector. std::vector didn't assume anything about T remember? so it can't catch the exception.  Well, choosing to not catch the exception instantly means that items[end] is no longer going to be destructed! Even if you catch the exception in your code, std::vector is now in an inconsistent state. Your std::vector "lost" an element.Compare that to a version with no return value.T std::vector<T>::pop_back(){  --end;  ~items[end];}//......try{  T last_item = my_vector.pop_back();}catch{}If the destructor throws, std::vector is done doing it's job. The vector is still consistent.   ;  But if you change the order around:T std::vector<T>::pop_back(){  T item = this->back();  --end;    ~items[end];  return item; }The real problem is that the return statement (by copy) can throw, in which case the object has been removed from the vector, but the caller never got hold of it at all.Perhaps other reasons are efficiency. Why should the user not have an efficient way to remove the last element if they are not interested in the removed item? Particularly seeing that there are ways to get hold of the last item before removing. (The question probably makes more sense with adapters like stack: why should they have a separate top and pop method, why not combine the two?)[Edited by - visitor on May 11, 2010 2:50:11 AM];Quote:Original post by visitorBut if you change the order around:That doesn't help.  The fundamental problem is that there are multiple failure points.  In your code if the exception happens before the --end then the vector retains it's original size.  If it happens afterwords then the vector is smaller.  The STL wants to be general purpose.  You may want the "correct" state after an exception in pop_back to be one way or the other depending on your needs.  It can't do this and return return an element at the same time so it chooses not to do the return.Quote:Original post by visitorWhy should the user not have an efficient way to remove the last element if they are not interested in the removed item?I don't understand the problem...  back() is efficient as you point out.  pop_back() is also efficient.   ;Quote:That doesn't help. The fundamental problem is that there are multiple failure points. In your code if the exception happens before the --end then the vector retains it's original size. If it happens afterwords then the vector is smaller. The STL wants to be general purpose. You may want the "correct" state after an exception in pop_back to be one way or the other depending on your needs. It can't do this and return return an element at the same time so it chooses not to do the return.I was only pointing out that the vector's internal state won't necessarily be completely messed up, as a previous poster claimed. If the exception happened before actual erasing, that would be super (a rather strong exception guarantee: object stays in the original state). If the exception happens after, then yes, that is unfortunate: if you were interested in the returned value, then sorry, that is lost without a trace. (And if the exception came from the destructor, that would not be the vector's problem.)Quote:I don't understand the problem... back() is efficient as you point out. pop_back() is also efficient.Efficiency could well be a much more compelling reason: if pop_back returned the value, then that would mean I'd have to pay the price of a copy, even if I only wanted to erase the last item. (Also the single responsibility principle. Exception safety concerns are just so far down the list, that it is surprising you ever get there when discussing the design choices behind vector::pop_back.)This is also why I mentioned the question makes more sense with abstract data types like the stack. If I'm not mistaken, a stack is a kind of data structure where you are only supposed to read the top value once and then also pop it, that is, by definition it only allows you to push and pop values (as it may well be implemented in other languages). Why doesn't C++ enforce this property in the design of the container adaptors? Now this is a place where exception safety concerns play are large part.   ;Quote:Original post by visitorEfficiency could well be a much more compelling reason: if pop_back returned the value, then that would mean I'd have to pay the price of a copy, even if I only wanted to erase the last item.This is the reason I always recall hearing, not this exception safety business -- although it certainly seems applicable too.   