Moving the last element of a vector

Viewed 61

What is the most efficient way to obtain the last (heavy) element from a vector and remove it, and make as few copies as possible? Is it

template <typaname T>
T moveLastElement (std::vector<T>& vec) {
    T t = std::move(vec.back());
    vec.pop_back();
    return t;
}
1 Answers

Since we're talking about copy elision, and specifically NVRO, and I'm assuming @presto that you're compiling for (at minimum) C++17, there's an interesting edge case.

Suppose you have a function like this:

heavy_object fox_this_compiler ()
{
    heavy_object h1;
    heavy_object h2;

    return (some_condition_that_cant_be_evaluated_at_compile_time) ? h1 : h2;
}

Now the compiler's in a quandry, because it can't construct both h1 and h2 at the call site, and that's what NVRO depends on. So (and I just ran a quick test), it returns a copy (and one of you language lawyers can tell me why).

So this is a case where explicitly moving from the object you're returning is worthwhile, as you can see in the:

Live demo

I'm not sure if there's some kind of type trait to let you know if you need to do this in any particular instance, but if there is I don't know about it.


Edit: turns out there is a way. Just stick the call to std::move in there and if you don't need it, gcc will warn you (but if you do, it won't). Nifty. But, sadly, it won't warn you when you do need it and you fail to put it in.

Related