4

Since the constructor of std::shared_ptr is marked as explicit one, so expressions like auto p = std::make_shared<int>(1); p = new int(6); is wrong.

My question is why does std::make_shared<int>(1); p = nullptr; compile?

Here is the aforementioned code snippet:

#include <memory>
#include <iostream>

int main()
{
    auto p = std::make_shared<int>(1);

    //p = new int(6);

    p = nullptr;

    if(!p)
    {
        std::cout << "not accessable any more" << std::endl;
    }

    p.reset();
}

Such code is seen at std::shared_ptr: reset() vs. assignment

user438383
  • 5,716
  • 8
  • 28
  • 43
John
  • 2,963
  • 11
  • 33

1 Answers1

5

The raw pointer constructor is explicit to prevent you accidentally taking ownership of a pointer. As there is no concern taking ownership of nullptr the constructor taking std::nullptr_t is not marked explicit.

Note that this only applies to nullptr these other assignments of a null pointer might not work (depending on your compiler):

auto p = std::make_shared<int>(1);
p = NULL;
int * a = nullptr;
p = a;
Alan Birtles
  • 32,622
  • 4
  • 31
  • 60
  • 1
    I suggest you explain *why* `p = NULL` and `p = a` both fail (i.e. because `NULL` and `a` have types distinct from `std::nullptr_t`) and why the initialisation of `a` succeeds (i.e. because `nullptr` can be implicitly converted to an `int *`). – Peter Mar 13 '22 at 09:19
  • @Alan Birtles Thank you for the clarificatiion. What's more, as `constexpr shared_ptr() noexcept;` is not `explicit`, so [`std::unique_ptr p = {};`](https://godbolt.org/z/3cxqsxKv9) also works. Am I right> – John Mar 13 '22 at 09:24
  • @John I assume you mean `std::shared_ptr p = {}`? `explicit` doesn't come into this, that's just calling the default constructor, and `std::shared_ptr p; p = {};` is passing a default constructed `shared_ptr` into the assignment operator – Alan Birtles Mar 13 '22 at 09:51
  • @Alan Birtles I see, thank you so much. I think `std::shared_ptr p = {}` calls the copy constructor(i.e. `shared_ptr( const shared_ptr& r )` ) other than the default constructor. Am I right? – John Mar 13 '22 at 09:58
  • @John no, its the default constructor: https://godbolt.org/z/f18daeWKM – Alan Birtles Mar 13 '22 at 11:04
  • https://en.cppreference.com/w/cpp/types/NULL suggests to me that `NULL` should work, because it is a `std::nullptr_t` constant. godbolt.org agrees with me, BTW. The other assignment missing is with a zero integer literal, that seems to work as well. – Ulrich Eckhardt Mar 13 '22 at 12:14
  • @UlrichEckhardt depends on your compiler, `NULL` can be `0` or `nullptr` – Alan Birtles Mar 13 '22 at 12:41