{"id":493,"date":"2021-03-05T09:54:24","date_gmt":"2021-03-05T09:54:24","guid":{"rendered":"https:\/\/tbekk.com\/devstream\/?p=493"},"modified":"2021-03-05T09:55:35","modified_gmt":"2021-03-05T09:55:35","slug":"dont-blindly-prefer-emplace_back-to-push_back","status":"publish","type":"post","link":"https:\/\/tbekk.com\/devstream\/2021\/03\/05\/dont-blindly-prefer-emplace_back-to-push_back\/","title":{"rendered":"Don\u2019t blindly prefer emplace_back to push_back"},"content":{"rendered":"\n<ul class=\"wp-block-list\"><li><em>Published at: <a href=\"https:\/\/quuxplusone.github.io\/blog\/2021\/03\/03\/push-back-emplace-back\/\">https:\/\/quuxplusone.github.io\/blog\/2021\/03\/03\/push-back-emplace-back\/<\/a><\/em><\/li><li><em>Author: Arthur O\u2019Dwyer<\/em><\/li><li><em>Publication date: March 3, 2021<\/em><\/li><\/ul>\n\n\n\n<hr class=\"wp-block-separator\"\/>\n\n\n\n<p id=\"in-one-of-my-recent-training-cou\">In one of my recent training courses, a student informed me that both clang-tidy and PVS-Studio were complaining about some code of the form<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>std::vector&lt;Widget> widgets;\n~~~\nwidgets.push_back(Widget(foo, bar, baz));<\/code><\/pre>\n\n\n\n<p id=\"both-tools-flagged-this-line-as\">Both tools flagged this line as \u201cbad style.\u201d clang-tidy even offered a (SARCASM ALERT) helpful fixit:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>warning: use emplace_back instead of push_back &#91;modernize-use-emplace]\n    widgets.push_back(Widget(foo, bar, baz));\n            ^~~~~~~~~~~~~~~~~             ~\n            emplace_back(<\/code><\/pre>\n\n\n\n<p id=\"the-student-dutifully-changed-th\">The student dutifully changed the line, and both tools reported their satisfaction with the replacement:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>widgets.emplace_back(Widget(foo, bar, baz));\n<\/code><\/pre>\n\n\n\n<p id=\"the-original-line-materializes-a\">The original line materializes a temporary&nbsp;<code>Widget<\/code>&nbsp;object on the stack; takes an rvalue reference to it; and passes that reference to&nbsp;<code>vector&lt;Widget&gt;::push_back(Widget&amp;&amp;)<\/code>, which move-constructs a&nbsp;<code>Widget<\/code>&nbsp;into the vector. Then we destroy the temporary.<\/p>\n\n\n\n<p id=\"the-student-s-replacement-materi\">The student\u2019s replacement materializes a temporary&nbsp;<code>Widget<\/code>&nbsp;object on the stack; takes an rvalue reference to it; and passes that reference to&nbsp;<code>vector&lt;Widget&gt;::emplace_back&lt;Widget&gt;(Widget&amp;&amp;)<\/code>, which move-constructs a&nbsp;<code>Widget<\/code>&nbsp;into the vector. Then we destroy the temporary.<\/p>\n\n\n\n<p id=\"absolutely-no-difference.\"><em>Absolutely no difference.<\/em><\/p>\n\n\n\n<p id=\"the-change-clang-tidy-meant-to-s\">The change clang-tidy meant to suggest \u2014 and in fact&nbsp;<em>did<\/em>&nbsp;suggest, if you pay very close attention to the underlining in the fixit \u2014 was actually this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>widgets.emplace_back(foo, bar, baz);<\/code><\/pre>\n\n\n\n<p id=\"this-version-does-not-materializ\">This version does&nbsp;<em>not<\/em>&nbsp;materialize any&nbsp;<code>Widget<\/code>&nbsp;temporaries. It simply passes&nbsp;<code>foo, bar, baz<\/code>&nbsp;to&nbsp;<code>vector&lt;Widget&gt;::emplace_back&lt;Foo&amp;, Bar&amp;, Baz&amp;&gt;(Foo&amp;, Bar&amp;, Baz&amp;)<\/code>, which constructs a&nbsp;<code>Widget<\/code>&nbsp;into the vector using whatever constructor of&nbsp;<code>Widget<\/code>&nbsp;best matches that bunch of arguments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"emplace_back-is-not-magic-c11-pixie-dust\"><code>emplace_back<\/code>&nbsp;is not magic C++11 pixie dust<\/h2>\n\n\n\n<p id=\"even-a-decade-after-c-11-was-rel\">Even a decade after C++11 was released, I still sometimes see programmers assume that&nbsp;<code>emplace_back<\/code>&nbsp;is somehow related to move semantics. (In the same way that some programmers assume lambdas are somehow the same thing as&nbsp;<code>std::function<\/code>, you know?) For example, they\u2019ll rightly observe that this code makes an unnecessary copy:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void example() {\n    auto w = Widget(1,2,3);\n    widgets.push_back(w);  \/\/ Copy-constructor alert!\n}<\/code><\/pre>\n\n\n\n<p id=\"so-they-ll-change-it-to-this\">So they\u2019ll change it to this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void example() {\n    auto w = Widget(1,2,3);\n    widgets.emplace_back(w);  \/\/ Fixed? Nope!\n}<\/code><\/pre>\n\n\n\n<p id=\"the-original-line-constructs-a-w\">The original line constructs a&nbsp;<code>Widget<\/code>&nbsp;object into&nbsp;<code>w<\/code>, then passes&nbsp;<code>w<\/code>&nbsp;by reference to&nbsp;<code>vector&lt;Widget&gt;::push_back(const Widget&amp;)<\/code>, which copy-constructs a&nbsp;<code>Widget<\/code>&nbsp;into the vector.<\/p>\n\n\n\n<p id=\"the-replacement-constructs-a-wid\">The replacement constructs a&nbsp;<code>Widget<\/code>&nbsp;object into&nbsp;<code>w<\/code>, then passes&nbsp;<code>w<\/code>&nbsp;by reference to&nbsp;<code>vector&lt;Widget&gt;::emplace_back&lt;Widget&amp;&gt;(Widget&amp;)<\/code>, which copy-constructs a&nbsp;<code>Widget<\/code>&nbsp;into the vector.<\/p>\n\n\n\n<p id=\"absolutely-no-difference.-1\"><em>Absolutely no difference.<\/em><\/p>\n\n\n\n<p id=\"what-the-student-should-have-don\">What the student should have done is ask the compiler to make an&nbsp;<em>rvalue<\/em>&nbsp;reference to&nbsp;<code>w<\/code>, by saying either<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>widgets.push_back(std::move(w));<\/code><\/pre>\n\n\n\n<p id=\"or\">or<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>widgets.emplace_back(std::move(w));<\/code><\/pre>\n\n\n\n<p id=\"it-doesn-t-matter-which-verb-you\">It doesn\u2019t matter which verb you use; what matters is the value category of&nbsp;<code>w<\/code>. You must explicitly mention&nbsp;<code>std::move<\/code>, so that the language (and the human reader) understand that you\u2019re done using&nbsp;<code>w<\/code>&nbsp;and it\u2019s okay for&nbsp;<code>widgets<\/code>&nbsp;to pilfer its guts.<\/p>\n\n\n\n<p id=\"emplace_back-was-added-to-the-la\"><code>emplace_back<\/code>&nbsp;was added to the language at the same time as&nbsp;<code>std::move<\/code>&nbsp;\u2014 just like lambdas were added at the same time as&nbsp;<code>std::function<\/code>&nbsp;\u2014 but that doesn\u2019t make them the same thing.&nbsp;<code>emplace_back<\/code>&nbsp;may \u201clook more C++11-ish,\u201d but it\u2019s not magic move-enabling pixie dust and it will never insert a move in a place you don\u2019t explicitly request one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"when-all-else-is-equal-prefer-push_back-to-emplace_back\">When all else is equal, prefer&nbsp;<code>push_back<\/code>&nbsp;to&nbsp;<code>emplace_back<\/code><\/h2>\n\n\n\n<p id=\"so-given-that-these-two-lines-do\">So, given that these two lines do the same thing and are equally efficient at runtime, which should I prefer, stylistically?<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>widgets.push_back(std::move(w));\nwidgets.emplace_back(std::move(w));\n<\/code><\/pre>\n\n\n\n<p id=\"i-recommend-sticking-with-push_b\">I recommend sticking with&nbsp;<code>push_back<\/code>&nbsp;for day-to-day use. You should definitely use&nbsp;<code>emplace_back<\/code>&nbsp;when you need its particular set of skills \u2014 for example,&nbsp;<code>emplace_back<\/code>&nbsp;is your only option when dealing with a&nbsp;<code>deque&lt;mutex&gt;<\/code>&nbsp;or other non-movable type \u2014 but&nbsp;<code>push_back<\/code>&nbsp;is the appropriate default.<\/p>\n\n\n\n<p id=\"one-reason-is-that-emplace_back\">One reason is that&nbsp;<code>emplace_back<\/code>&nbsp;is more work for the compiler.&nbsp;<code>push_back<\/code>&nbsp;is an overload set of two non-template member functions.&nbsp;<code>emplace_back<\/code>&nbsp;is a single variadic template.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void push_back(const Widget&amp;);\nvoid push_back(Widget&amp;&amp;);\n\ntemplate&lt;class... Ts>\nreference emplace_back(Ts&amp;&amp;...);<\/code><\/pre>\n\n\n\n<p id=\"when-you-call-push_back-the-comp\">When you call&nbsp;<code>push_back<\/code>, the compiler must do overload resolution, but that\u2019s all. When you call&nbsp;<code>emplace_back<\/code>, the compiler must do template type deduction, followed by (easy-peasy) overload resolution, followed by function template instantiation and code generation. That\u2019s a much larger amount of work for the compiler.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"the-benchmark-program\">The benchmark program<\/h2>\n\n\n\n<p id=\"i-wrote-a-simple-test-program-to\">I wrote a simple test program to demonstrate the difference in compiler workload. Of course&nbsp;<a href=\"https:\/\/en.wikipedia.org\/wiki\/Amdahl%27s_law\">Amdahl\u2019s Law<\/a>&nbsp;applies: my benchmark displays a massive difference because it\u2019s doing&nbsp;<em>nothing but<\/em>&nbsp;instantiating&nbsp;<code>emplace_back<\/code>, whereas any production codebase will be doing vastly more other stuff relative to the number of times it instantiates&nbsp;<code>emplace_back<\/code>. Still, I hope this benchmark gives you a sense of why I recommend \u201c<code>push_back<\/code>&nbsp;over&nbsp;<code>emplace_back<\/code>\u201d and not vice versa.<\/p>\n\n\n\n<p id=\"this-python-3-script-generates-t\">This Python 3 script generates the benchmark:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>import sys\nprint('#include &lt;vector>')\nprint('#include &lt;string>')\nprint('extern std::vector&lt;std::string> v;')\nfor i in range(1000):\n    print('void test%d() {' % i)\n    print('    v.%s_back(\"%s\");' % (sys.argv&#91;1], 'A' * i))\n    print('}')<\/code><\/pre>\n\n\n\n<p id=\"generate-like-this\">Generate like this:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>python generate.py push >push.cpp\npython generate.py emplace >emplace.cpp\ntime g++ -c push.cpp\ntime g++ -c emplace.cpp<\/code><\/pre>\n\n\n\n<p id=\"with-clang-trunk-on-my-laptop-i\">With Clang trunk on my laptop, I get consistently about 1.0s for the&nbsp;<code>push<\/code>&nbsp;version, and 4.2s for the&nbsp;<code>emplace<\/code>&nbsp;version. This big difference is due to the fact that the&nbsp;<code>push<\/code>&nbsp;version is merely code-generating a thousand&nbsp;<code>test<\/code>&nbsp;functions, whereas the&nbsp;<code>emplace<\/code>&nbsp;version is code-generating that same thousand&nbsp;<code>test<\/code>&nbsp;functions&nbsp;<em>and<\/em>&nbsp;another thousand template instantiations of&nbsp;<code>emplace_back<\/code>&nbsp;with different parameter types:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>vector&lt;string>::emplace_back&lt;const char(&amp;)&#91;1]>(const char (&amp;)&#91;1])\nvector&lt;string>::emplace_back&lt;const char(&amp;)&#91;2]>(const char (&amp;)&#91;2])\nvector&lt;string>::emplace_back&lt;const char(&amp;)&#91;3]>(const char (&amp;)&#91;3])\nvector&lt;string>::emplace_back&lt;const char(&amp;)&#91;4]>(const char (&amp;)&#91;4])\n~~~<\/code><\/pre>\n\n\n\n<p id=\"see-push_back-knows-that-it-expe\">See,&nbsp;<code>push_back<\/code>&nbsp;knows that it expects a&nbsp;<code>string&amp;&amp;<\/code>, and so it knows to call the non-explicit constructor&nbsp;<code>string(const char *)<\/code>&nbsp;on the caller\u2019s side. The same constructor is called in each case, and the temporary&nbsp;<code>string<\/code>&nbsp;is passed to the same overload of&nbsp;<code>push_back<\/code>&nbsp;in each case.&nbsp;<code>emplace_back<\/code>, on the other hand, is a dumb perfect-forwarding template: it doesn\u2019t know that the relevant constructor overload will end up being&nbsp;<code>string(const char *)<\/code>&nbsp;in each case. So it takes an lvalue reference to the specific&nbsp;<em>array type<\/em>&nbsp;being passed by the caller. Perfect-forwarding has no special cases for&nbsp;<code>const char *<\/code>!<\/p>\n\n\n\n<p id=\"if-we-change-vector-string-to-ve\">If we change&nbsp;<code>vector&lt;string&gt;<\/code>&nbsp;to&nbsp;<code>vector&lt;const char *&gt;<\/code>, the compile-time-performance gap widens: now it\u2019s 0.7s for&nbsp;<code>push<\/code>, 3.8s for&nbsp;<code>emplace<\/code>. This is because we\u2019ve cut out some of the work that was common to both versions (constructing&nbsp;<code>std::string<\/code>&nbsp;objects) without affecting the source of the gap (that one version instantiates a thousand copies of&nbsp;<code>emplace_back<\/code>&nbsp;and the other doesn\u2019t). Amdahl\u2019s Law in action!<\/p>\n\n\n\n<p id=\"my-conclusions\">My conclusions:<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Use&nbsp;<code>push_back<\/code>&nbsp;by default.<\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Use&nbsp;<code>emplace_back<\/code>&nbsp;where it is semantically significant to your algorithm (such as when the element type\u2019s move-constructor is absent or has been benchmarked as expensive).<\/p><\/blockquote>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\"><p>Avoid mixing string literals and perfect-forwarding templates, especially in repetitive machine-generated code.<\/p><\/blockquote>\n","protected":false},"excerpt":{"rendered":"<p>Published at: https:\/\/quuxplusone.github.io\/blog\/2021\/03\/03\/push-back-emplace-back\/ Author: Arthur O\u2019Dwyer Publication date: March 3, 2021 In one of my recent training courses, a student informed me that both clang-tidy and PVS-Studio were complaining about&#8230; <a class=\"read-more-link\" href=\"https:\/\/tbekk.com\/devstream\/2021\/03\/05\/dont-blindly-prefer-emplace_back-to-push_back\/\">Read more &raquo;<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[51,87,10],"tags":[77],"class_list":["post-493","post","type-post","status-publish","format-standard","hentry","category-article","category-coding","category-development","tag-c-3"],"_links":{"self":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/493","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/comments?post=493"}],"version-history":[{"count":1,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/493\/revisions"}],"predecessor-version":[{"id":494,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/posts\/493\/revisions\/494"}],"wp:attachment":[{"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/media?parent=493"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/categories?post=493"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tbekk.com\/devstream\/wp-json\/wp\/v2\/tags?post=493"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}