title: Performance of resizing std::vector<std::unique_ptr<T>>
body: <p>The general conception seems to be that <code>std::unique_ptr</code> has <a href="https://stackoverflow.com/questions/22295665/how-much-is-the-overhead-of-smart-pointers-compared-to-normal-pointers-in-c">no time overhead</a> compared to properly used owning raw pointers, <a href="https://stackoverflow.com/questions/28896490/why-is-stdunique-ptr-much-slower-than-standard-pointer-before-optimizations">given sufficient optimization</a>.</p>
  
  <p>But what about using <code>std::unique_ptr</code> in compound data structures, in particular <code>std::vector&lt;std::unique_ptr&lt;T&gt;&gt;</code>? For instance, resizing the underlying data of a vector, which can happen during <code>push_back</code>. To isolate the performance, I loop around <code>pop_back</code>, <code>shrink_to_fit</code>, <code>emplace_back</code>:</p>
  
  <pre><code>#include &lt;chrono&gt;
  #include &lt;vector&gt;
  #include &lt;memory&gt;
  #include &lt;iostream&gt;
  
  constexpr size_t size = 1000000;
  constexpr size_t repeat = 1000;
  using my_clock = std::chrono::high_resolution_clock;
  
  template&lt;class T&gt;
  auto test(std::vector&lt;T&gt;&amp; v) {
      v.reserve(size);
      for (size_t i = 0; i &lt; size; i++) {
          v.emplace_back(new int());
      }
      auto t0 = my_clock::now();
      for (int i = 0; i &lt; repeat; i++) {
          auto back = std::move(v.back());
          v.pop_back();
          v.shrink_to_fit();
          if (back == nullptr) throw "don't optimize me away";
          v.emplace_back(std::move(back));
      }
      return my_clock::now() - t0;
  }
  
  int main() {
      std::vector&lt;std::unique_ptr&lt;int&gt;&gt; v_u;
      std::vector&lt;int*&gt; v_p;
  
      auto millis_p = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(test(v_p));
      auto millis_u = std::chrono::duration_cast&lt;std::chrono::milliseconds&gt;(test(v_u));
      std::cout &lt;&lt; "raw pointer: " &lt;&lt; millis_p.count() &lt;&lt; " ms, unique_ptr: " &lt;&lt; millis_u.count() &lt;&lt; " ms\n";
      for (auto p : v_p) delete p; // I don't like memory leaks ;-)
  }
  </code></pre>
  
  <p>Compiling the code with <code>-O3 -o -march=native -std=c++14 -g</code> with gcc 7.1.0, clang 3.8.0, and 17.0.4 on Linux on a Intel Xeon E5-2690 v3 @ 2.6 GHz (no turbo):</p>
  
  <pre><code>raw pointer: 2746 ms, unique_ptr: 5140 ms  (gcc)
  raw pointer: 2667 ms, unique_ptr: 5529 ms  (clang)
  raw pointer: 1448 ms, unique_ptr: 5374 ms  (intel)
  </code></pre>
  
  <p>The raw pointer version spends all it's time in an optimized <code>memmove</code> (intel seems to have a much better one than clang and gcc). The <code>unique_ptr</code> code seems to first copy over the vector data from one memory block to the other and assign the original one with zero - all in a horribly un-optimized loop. And then it loops over the original block of data again to see if any of those that were just zero'd are nonzero and need to be deleted. The full gory detail can be seen on <a href="https://godbolt.org/g/S6P8Fm" rel="noreferrer">godbolt</a>. <strong>The question is not how the compiled code differs</strong>, that is pretty clear. The question is <strong>why</strong> the compiler fails to optimize what is generally regarded as a no-extra-overhead abstraction.</p>
  
  <p>Trying to understand how the compilers reason about handling <code>std::unique_ptr</code>, I was looking a bit more at isolated code. For instance:</p>
  
  <pre><code>void foo(std::unique_ptr&lt;int&gt;&amp; a, std::unique_ptr&lt;int&gt;&amp; b) {
    a.release();
    a = std::move(b);
  }
  </code></pre>
  
  <p>or the similar</p>
  
  <pre><code>a.release();
  a.reset(b.release());
  </code></pre>
  
  <p>none of the x86 compilers <a href="https://godbolt.org/g/7sY5Dm" rel="noreferrer">seem to be able to optimize away</a> the senseless <code>if (ptr) delete ptr;</code>. The Intel compiler even gives the delete a 28 % chance. Surprisingly, the delete check is consistently omitted for:</p>
  
  <pre><code>auto tmp = b.release();
  a.release();
  a.reset(tmp);
  </code></pre>
  
  <p>These bits are not the main aspect of this question, but all of this  makes me feel that I am missing something.</p>
  
  <p>Why do various compilers fail to optimize reallocation within <code>std::vector&lt;std::unique_ptr&lt;int&gt;&gt;</code>? Is there anything in the standard that prevents generating code as efficient as with raw pointers? Is this an issue with the standard library implementation? Or are the compilers just not sufficiently clever enough (yet)?</p>
  
  <p>What can one do to avoid performance impact compared to using raw pointers?</p>
  
  <p>Note: Assume that <code>T</code> is polymorphic and expensive to move, so <code>std::vector&lt;T&gt;</code> is not an option.</p>