Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are there two overloads for vector::push_back?

Tags:

c++

c++11

Why doesn't vector::push_back take a forwarding reference instead of having two overloads? I've read that the only reason you'd want to overload on lvalues and rvalues is if your functions do something differently for them, so how do both overloads of vector::push_back differ other than moving/copying?

like image 837
template boy Avatar asked Jan 24 '15 21:01

template boy


People also ask

What does vector Push_back do in C++?

C++ Vector Library - push_back() Function The C++ function std::vector::push_back() inserts new element at the end of vector and increases size of vector by one.

What does Push_back in C++ mean?

push_back method() in C++ is a method that is part of the vector as a data structure in C++. It is used for pushing elements from the back of the vector.

Does std::vector Push_back make a copy?

Yes, std::vector<T>::push_back() creates a copy of the argument and stores it in the vector.

What does Push_back mean?

The push_back() function is used to insert an element at the end of a vector. This function is available in the <vector> header file.


1 Answers

I did this largely just because of how the situation evolved. Prior to C++11, there was only:

vector<T>::push_back(const T&); 

With the introduction of rvalue references I recommended the addition of the overload:

vector<T>::push_back(T&&); 

instead of changing the original signature to:

template <class U> vector<T>::push_back(U&&); 

Part of this decision was made because of some concerns about backward compatibility (whether warranted or not), and to ease concerns of both vendors and others on the committee that this was a simple addition of functionality, and not a change to existing functionality.

If I were redesigning vector from scratch today, I would seriously consider just having:

template <class U> vector<T>::push_back(U&&); 

or perhaps just:

template <class ...Args> vector<T>::emplace_back(Args&& ...); 

More details than you probably want to know about are in N1858.

Why not push_back by value?

This question has been marked as a duplicate of:

Why do C++11 std containers have pass-by-ref and pass-by-rvalue insert/push methods?

which asks this question. So I figured it would be the polite thing to do to actually address that aspect in this answer...

For lvalues and xvalues, a push_back(T) would cost an extra move construction compared to the by-reference solutions. xvalues would require 2 move constructions and lvalues would require 1 copy construction and 1 move construction.

In contrast, with the current design, lvalues cost 1 copy construction and xvalues cost 1 move construction.

For some types T, move construction is not cheap. It would be a poor design choice for vector<T> to assume that T is always cheaply movable. For example what if T is std::array<double, 100>? Changing to the by-value design would require 2 copy constructions instead of 1 to push_back (except for prvalues).

The by-value solution does have advantages, and times when it should be used. It is just that vector<T>::push_back() is not one of those times.

like image 170
Howard Hinnant Avatar answered Oct 02 '22 09:10

Howard Hinnant