简体   繁体   中英

error when defining a std::shared_ptr with new operator

I am trying to define a std::shared_ptr with new operator in the following way:

#include <memory>

struct A {
};

int main() {

  std::shared_ptr<A> ptr = new A();

  return 0;
}

but I obtained the following compile-time error:

main.cpp: In function 'int main()':

main.cpp:8:30: error: conversion from 'A*' to non-scalar type 'std::shared_ptr' requested std::shared_ptr ptr = new A();

Anyway, the following definitely works:

      std::shared_ptr<A> ptr{new A()};

Does anyone of you know why this happens?

tl;dr: it's a consequence of the relevant constructor being explicit .

When you initialise with = , you invoke copy-initialisation. C++ does not allow copy-initialisation of a shared_ptr from a raw pointer, because it would be too easy to end up with an accidental implicit conversion from some arbitrary raw pointer into a shared_ptr that doesn't actually manage it.

This way, the only way you can "ensnare" a raw pointer into a shared_ptr is very deliberately and very explicitly (as you have correctly done in your second example). Now, only in this initialiser do you have to remember not to do so with a pointer you're already managing elsewhere.

Is there anything actually dangerous about the specific line std::shared_ptr<A> ptr = new A() ? No. But what you're seeing is a consequence of various C++ rules working together in concert.

You can imagine your statement also as a 2 liner like this.

A* a = new A();
std::shared_ptr<A> ptr = a;

While in this case this may be correct in more complicated code it can lead to potential pitfalls so copy initialization is not allowed to a raw pointer.

Imagine

A* a = new A();
//.....
std::shared_ptr<A> ptr = a;
//.....
std::shared_ptr<A> ptr2 = a; //second ptr holding a... UB

Here you would have 2 shared pointers holding the same object which causes trouble.

To avoid those "implicit" errors C++ is not allowing this kind of initialization.

While you can still to the same with constructors but it is more "verbose" and harder to accidentally assign pointers.

std::shared_ptr<A> ptr{ new A() };

This looks more like constructing a new object and may not result in an mis-assignment by accident.

Also the preferred way to create a shared pointer in modern is

auto ptr = std::make_shared<A>();

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM