Jump to content
  • Advertisement
Sign in to follow this  
Guthur

void std::vector::pop_back

This topic is 3502 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Why the void return type. I got this as a question in a test and it has been bugging me. Is it because there would be no meaningful return type, as it will always succeed even if empty, and to return a bool saying an element has been removed is pretty meaningless.

Share this post


Link to post
Share on other sites
Advertisement
The only meaningful return value in my oppinion would be the object being popped, so that you can do myObj = myObjVector.pop_back() for example (grab the last one and remove it in one go). The problem with this, though, is that you must return by value. You cannot return it by reference since the object was just removed from the vector.

Share this post


Link to post
Share on other sites
There would be no meaningful data to return because the object would have been destructed from the pop_back operation if it was not a pointer. In that event, you can assume the object was no longer needed, so if you did return something, it would be creating a new copy of the object which should have been "removed".

Consider the output of the following program:

#include <vector>
#include <iostream>

class MyClass
{
int filler;

public:
MyClass()
: filler(0)
{
std::cout << "ctor" << std::endl;
}

MyClass(const MyClass & rhs)
{
filler = rhs.filler;
std::cout << "copy ctr" << std::endl;
}

~MyClass()
{
std::cout << "dtor" << std::endl;
}
};

int main(int argc, char * argv[])
{
std::vector<MyClass> vec;
MyClass c;

std::cout << "- 1 --" << std::endl;
vec.push_back(c);
std::cout << "- 2 --" << std::endl;
vec.pop_back();
std::cout << "---" << std::endl;
return 0;
}





ctor
- 1 --
copy ctr
copy ctr
dtor
- 2 --
dtor
---
dtor
Press any key to continue . . .




The first "ctor" is from c being constructed in main. The next two "copy ctor" are generated inside the push_back function, which emphasizes the possible dangers of using an incorrect class design. The following dtor is one temporary object that is cleaned up inside push_back again. The following dtor is from the pop_back call which destructs the object that was stored.

If it were to return what the last value was, it would be calling the ctor again and depending on your class design, that would be a bad thing since you now have a new object created. The last dtor is from c being destructed, as expected.

Besides those ramifications, the design of the standard C++ library is that of, one function, one purpose (more or less). If you need to last item of a vector, you can use an iterator, (vec.end() - 1), since .end() returns the element one after the last item. If you want to remove the last item, you can simply use pop_back, which does the same thing as if you were to call, vec.erase(vec.end() - 1). In both those cases, the actions of either getting or removing are "separate".

[edit]Pretty much reexplaining what Brother Bob posted ^^

Share this post


Link to post
Share on other sites
Indeed, the most logical return type would be to return the data you just popped (like a stack). But I guess that's what std::stack is for.

To return a boolean that specifies if the vector was successfully popped would work, but there are other ways to check that. And I'm guessing the STL team wanted to make it as straightforward as possible.

So all that remains is to return void (e.g. nothing).

Share this post


Link to post
Share on other sites
It threw me somewhat I admit, I think I was blinded by the simplicity of the question. I never questioned it before and then the question just made me think I was missing something.

Edit: Oh and returning the object removed would cause issues I would think, as has been mentioned, and also what would you return if the vector was indeed empty.

Share this post


Link to post
Share on other sites
Quote:
Original post by HomerSp
Indeed, the most logical return type would be to return the data you just popped (like a stack). But I guess that's what std::stack is for.


Just for reference, the stack, queue, and vector containers all are designed similarly in that, the push/pop family methods are void return types. You have to use the top/front/iterator or index operators, respectively, to actually get any data.

Share this post


Link to post
Share on other sites
Great articles, thanks Phresnel.

So in essence it is simplicity of design for exception safety's sake, not that I actually think much could be gained from having pop return anything; you can easily get the last element (safely), if required, before popping. My interpretation (now) is that it is the KISS approach.

It was a bit of a curve ball, especially for the level I thought the role in question was.

Share this post


Link to post
Share on other sites
Other languages/libraries often return a (copy) of the element that was removed when "popping" -- If memory serves, this was avoided in the SC++L for "speed" (un-necessary copying -- e.g. if you don't need the returned element -- could be wasteful).

Share this post


Link to post
Share on other sites
Quote:
Original post by phresnel
pop_back() is guaranteed to not throw, but that guarantee can't be hold up with non-void pop:


Great articles there, phresnel. I've been starting to compile my bits and pieces of utility code into usable libraries, and even though it is in Ruby, I run into these same exception issues. Great stuff there. Thanks!

Rates++.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!