Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
menu search
person
Welcome To Ask or Share your Answers For Others

Categories

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
320 views
Welcome To Ask or Share your Answers For Others

1 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
thumb_up_alt 0 like thumb_down_alt 0 dislike
Welcome to ShenZhenJia Knowledge Sharing Community for programmer and developer-Open, Learning and Share
...