title: Shouldn't `std::shared_ptr` use `std::default_delete` by default?
body: <p><a href="https://en.cppreference.com/w/cpp/memory/default_delete" rel="noreferrer"><code>std::default_delete</code></a> <a href="https://stackoverflow.com/questions/8513417/what-can-and-cant-i-specialize-in-the-std-namespace">can be specialized</a> to allow <a href="https://en.cppreference.com/w/cpp/memory/unique_ptr" rel="noreferrer"><code>std::unique_ptr</code></a>s to <a href="https://stackoverflow.com/a/50957671">painlessly manage types which have to be destroyed by calling some custom destroy-function instead of using <code>delete p;</code></a>.</p>
  
  <p>There are basically two ways to make sure an object is managed by a <a href="https://en.cppreference.com/w/cpp/memory/shared_ptr" rel="noreferrer"><code>std::shared_ptr</code></a> in C++:</p>
  
  <ol>
  <li><p>Create it managed by a shared-pointer, using <a href="https://en.cppreference.com/w/cpp/memory/shared_ptr/make_shared" rel="noreferrer"><code>std::make_shared</code></a> or <a href="https://en.cppreference.com/w/cpp/memory/shared_ptr/allocate_shared" rel="noreferrer"><code>std::allocate_shared</code></a>. This is the preferred way, as it coalesces both memory-blocks needed (payload and reference-counts) into one. Though iff there are only <a href="https://en.cppreference.com/w/cpp/memory/weak_ptr" rel="noreferrer"><code>std::weak_ptr</code></a>s left, the need for the reference-counts will by necessity still pin down the memory for the payload too.</p></li>
  <li><p>Assign management to a shared-pointer afterwards, using <a href="https://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr" rel="noreferrer">a constructor</a> or <a href="https://en.cppreference.com/w/cpp/memory/shared_ptr/reset" rel="noreferrer"><code>.reset()</code></a>.</p></li>
  </ol>
  
  <p>The second case, when not providing a custom deleter is interesting:</p>
  
  <p>Specifically, it is defined to use its own deleter of unspecified type which uses <code>delete [] p;</code> or <code>delete p;</code> respectively, depending on the <code>std::shared_ptr</code> being instantiated for an Array or not.</p>
  
  <p>Quote from n4659 (~C++17):</p>
  
  <blockquote>
  <pre><code>template&lt;class Y&gt; explicit shared_ptr(Y* p);
  </code></pre>
    
    <p>4 Requires: <code>Y</code> shall be a complete type. The expression <code>delete[] p</code>, when <code>T</code> is an array type, or <code>delete p</code>, when <code>T</code> is not an array type, shall have well-deﬁned behavior, and shall not throw exceptions.<br>
    5 Eﬀects: When <code>T</code> is not an Array type, constructs a <code>shared_ptr</code> object that owns the pointer <code>p</code>. Otherwise, constructs a <code>shared_ptr</code> that owns <code>p</code> and a deleter of an unspeciﬁed type that calls <code>delete[] p</code>. When <code>T</code> is not an array type, enables <code>shared_from_this</code> with <code>p</code>. If an exception is thrown, <code>delete p</code> is called when <code>T</code> is not an array type, <code>delete[] p</code> otherwise.<br>
    6 Postconditions: <code>use_count() == 1 &amp;&amp; get() == p</code>.<br>
    […]</p>
  
  <pre><code>template&lt;class Y&gt; void reset(Y* p);
  </code></pre>
    
    <p>3 Eﬀects: Equivalent to <code>shared_ptr(p).swap(*this)</code>.</p>
  </blockquote>
  
  <p>My questions are:</p>
  
  <ol>
  <li>Is there a, preferably good, reason that it is not specified to use <code>std::default_delete</code> instead?</li>
  <li>Would any valid (and potentially useful?) code be broken by that change?</li>
  <li>Is there already a proposal to do so?</li>
  </ol>