Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does emplace_back("Hello") call strlen?

Justin's answer on another question made an observation that I find very interesting but can't quite explain. Consider the following code:

std::vector<std::string> v;
v.push_back("Hello, world!");  // Doesn't call strlen.
v.emplace_back("Hello, world!");  // Calls strlen.

If you look at the assembly, emplace_back generates a call to strlen, whereas push_back does not (tested in gcc 8.1 and clang 6.0 using -Ofast).

Why is this happening? Why can't emplace_back optimize out the strlen call here? My initial thought was that push_back is implicitly creating the std::string before the function call (so the std::string constructor is directly passed the string literal, which is optimally handled), whereas emplace_back creates the std::string after the function call (so the std::string constructor is forwarded the string literal, which I presumed had decayed from a const char [N] to a const char *, thus requiring a strlen call).

But emplace_back takes a T&& parameter, and my tests show that the string literal shouldn't be decaying to a pointer here. Clearly I'm overlooking something.

like image 526
Cornstalks Avatar asked Jul 07 '18 03:07

Cornstalks


People also ask

Should I always use Emplace_back?

If you intend to call explicit constructors, then you need the power of emplace_back . If you want to call only implicit constructors, stick with the safety of push_back .

Why is emplace back faster than push back?

because emplace_back would construct the object immediately in the vector, while push_back , would first construct an anonymous object and then would copy it to the vector.


1 Answers

The strlen call is in the out-of-line function body for the slow path; that function body must be valid for all arguments of type const char (&)[42] (in your godbolt example), including arguments that did not originate from a string literal of 41 characters with no embedded nulls.

The fast path is inlined into foo, and it does compute the length at compile time.

like image 156
T.C. Avatar answered Oct 16 '22 07:10

T.C.