简体   繁体   中英

No suitable constructor exists to convert from “dumb pointer” to “smart pointer”

struct A
{
    A(int a);
};

struct B
{
    B();
    void b(std::shared_ptr<A> a);
};

int main()
{
    A a(1);
    B b;
    b.b(&a);
}

So I got this error, sorry guys it's my frist time with the smart pointers!!

Error:

no suitable constructor exists to convert from "A *" to "std::tr1::shared_ptr<A>"

How do I fix this problem??

The entire point of a smart pointer is to have ownership. That is, it's responsible for the deallocation of whatever it's pointing it. It simply doesn't make sense to try to tell it to manage something that's already being managed by a completely different system.

In your case, a is already being automatically managed, why would you want to also be managed by a smart pointer? Even if that worked, you'd just be setting yourself for deleting it twice, which is UB.

Either give it something to own, like new A(1) , or change b to operate on something it doesn't own.

Others already ranted on the design error of your code, but not the real problem why the code doesn't even compile. shared_ptr has a constructor that accepts a raw pointer, but it is marked as explicit , which means you have to explicitly write out that you want to construct a shared_ptr instance. What your function call tries, is to do that construction implicitly, which isn't allowed because of the explicit keyword.

The following will compile but give undefined behaviour because the shared_ptr will (try to) delete an object which resides on the stack and is as such not deleteable:

b.b(shared_ptr<A>(&a)); // explicit construction

A special trait of shared_ptr is that you can pass the constructor a deleter, which will be called when the owned pointer should be deleted. You can just write and use a "noop" deleter, which does just nothing; the following will not invoke undefined behaviour and will not try to delete the stack variable:

// outside of main
void noop_deleter(A*){/*do nothing*/}

 // call...
b.b(shared_ptr<A>(&a, noop_deleter));

And there actually is a use for this, if you have a library API that absolutely wants a shared_ptr but you want to call it with a stack variable. The design of that API is another thing though...

std::tr1::shared_ptr has one constructor that allows to pass down a given raw pointer. So if you had a pointer to A, you would do something like:

std::shared_ptr (pMyA)

but in your case, your pointer to A points to an automatic variable NOT to a dynamically allocated memory resource that can be deleted after usage.

Something like this would be a better use case:

class B
{
  void b (shared_ptr <A> pA) {}
}

int main ()
{
  shared_ptr<A> pA (new A);
  B b;
  b.b (pA);
  ...
}

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