<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Llvm on Wuyukwi's Notebook</title><link>https://wuyukwi.duckdns.org/tags/llvm/</link><description>Recent content in Llvm on Wuyukwi's Notebook</description><generator>Hugo</generator><language>ja</language><lastBuildDate>Tue, 24 Jun 2025 12:40:20 +0900</lastBuildDate><atom:link href="https://wuyukwi.duckdns.org/tags/llvm/index.xml" rel="self" type="application/rss+xml"/><item><title>💡 C++ の emplace_back は push_back を完全に置き換えられるか？</title><link>https://wuyukwi.duckdns.org/posts/zenn-c73aa0d12885ff/</link><pubDate>Tue, 24 Jun 2025 12:40:20 +0900</pubDate><guid>https://wuyukwi.duckdns.org/posts/zenn-c73aa0d12885ff/</guid><description>&lt;blockquote&gt;
&lt;p&gt;📌 &lt;em&gt;この記事は &lt;a href="https://zenn.dev/wuyukwi/articles/c73aa0d12885ff"&gt;Zenn&lt;/a&gt; に投稿した内容のアーカイブです。&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="はじめに"&gt;はじめに&lt;/h2&gt;
&lt;p&gt;C++11 から導入された &lt;code&gt;emplace_back&lt;/code&gt; は、コンテナに要素をその場で構築できる便利なメソッドです。&lt;br&gt;
一方、それ以前から使われてきた &lt;code&gt;push_back&lt;/code&gt; とはどんな違いがあり、&lt;code&gt;emplace_back&lt;/code&gt; は完全に &lt;code&gt;push_back&lt;/code&gt; を代替できるのでしょうか？&lt;/p&gt;
&lt;p&gt;本記事では、&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;code&gt;emplace_back&lt;/code&gt; が本当に &lt;code&gt;push_back&lt;/code&gt; より常に速いのか&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;両者がどんなケースに使えるのか&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;実装の違いと注意点&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;について、自分なりに整理した考えをまとめます。&lt;/p&gt;
&lt;h2 id="push_back-と-emplace_back-の違い"&gt;&lt;code&gt;push_back&lt;/code&gt; と &lt;code&gt;emplace_back&lt;/code&gt; の違い&lt;/h2&gt;
&lt;h3 id="push_back"&gt;&lt;code&gt;push_back&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// C++20以降
constexpr void push_back(const T&amp;amp; value); // コピー
constexpr void push_back(T&amp;amp;&amp;amp; value); // ムーブ
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;push_back&lt;/code&gt; は、すでに生成されたオブジェクトをコピーまたはムーブして格納する関数です。&lt;/p&gt;
&lt;h3 id="emplace_back"&gt;&lt;code&gt;emplace_back&lt;/code&gt;&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;// C++20以降
template&amp;lt;class... Args&amp;gt;
constexpr reference emplace_back(Args&amp;amp;&amp;amp;... args); // その場で構築
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;emplace_back&lt;/code&gt; は、コンストラクタに渡す引数をそのまま受け取り、コンテナ内部で直接オブジェクトを構築します。そのため、&lt;strong&gt;中間オブジェクトなし&lt;/strong&gt; に要素を追加できる点が特徴です。&lt;/p&gt;
&lt;p&gt;これらの大きな違いは、&lt;code&gt;push_back&lt;/code&gt;が&lt;strong&gt;既に生成されたオブジェクト（T型）&lt;strong&gt;をコピーまたはムーブする一方で、&lt;code&gt;emplace_back&lt;/code&gt;は&lt;/strong&gt;任意のコンストラクタ引数からその場でT型のインスタンスを構築できる&lt;/strong&gt;点です。&lt;/p&gt;
&lt;h2 id="llvmにおける内部実装"&gt;LLVMにおける内部実装&lt;/h2&gt;
&lt;p&gt;以下はLLVM(libc++)における&lt;code&gt;push_back&lt;/code&gt;内部の実装です。&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;if (this-&amp;gt;__end_ != this-&amp;gt;__end_cap()) {
__construct_one_at_end(__x); // 残り容量がある場合、__xをコピーまたはムーブ構築
} else {
__push_back_slow_path(__x); // 足りない場合、新規領域を確保して再配置
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;__construct_one_at_end&lt;/code&gt; の中では、allocatorが提供する &lt;code&gt;construct()&lt;/code&gt; を使って、指定されたメモリにオブジェクトを構築しています。&lt;br&gt;
また、allocatorが &lt;code&gt;construct()&lt;/code&gt; を持たない場合には単純に in-place new を呼び出す仕組みです。&lt;/p&gt;</description></item></channel></rss>