std::shared_ptr is a
class template that can be used similar to normal pointers. Basically, it will keep track of how many "shared pointers" point to the same object and when there are no longer any pointers pointing to the object it will automatically delete the object.
std::shared_ptr<TypeA> means a "shared pointer to TypeA". This is similar to having a TypeA*.
You say TypeA is a pointer type. This is less common but not imposible. It just means the object that the shared pointer points to is a pointer. Yes, pointers are objects.
Shared pointers can be null just like regular pointers. There are many syntaxes that you can use to create a null shared pointer. Here are some of them:
1 2 3
|
std::shared_ptr<TypeA> handle_;
std::shared_ptr<TypeA> handle_ = nullptr;
std::shared_ptr<TypeA> handle_ { nullptr };
|
handle_ will be null in all three of these cases.
By default the object will get deleted using
delete. For this to work the object (i.e.
pointer in this case) need to have been created with
new (which is what happens if you construct objects using std::make_shared).
But sometimes you might want to use shared pointers for objects that have not been created with
new. So what you can do is pass a
custom deleter as a second constructor argument when constructing the shared pointer. A custom deleter is an object that has a function-call operator that accepts a pointer to the object. You can easily create such an object using a lambda.
The code you posted seems to contain a mistake. It should take a pointer to the TypeA object as argument. Something like this:
1 2 3 4 5
|
std::shared_ptr<TypeA> handle_{nullptr, [](TypeA* ptr) {
if (ptr) {
AFree(ptr); // ???
}
}};
|
I think the reason it compiled before was because you passed nullptr as the first argument which can be converted into any pointer type (you said TypeA is a pointer type), but I'm not sure if it is guaranteed to work, and it would not work if you passed a TypeA* instead of nullptr as first argument.
Anyhow, using a custom deleter for a null shared pointer seems a bit pointless. The default deleter would work just fine.
I wrote ??? in the deleter above because it's not clear if AFree actually wants to take a TypeA* as argument. In your code it seemed to take a TypeA as argument. If AFree just frees the object that is pointed to by the AFree object then you would still need to free the AFree* pointer in the deleter, possibly using delete but that depends on how it was created.
1 2 3 4 5 6
|
std::shared_ptr<TypeA> handle_{nullptr, [](TypeA* ptr) {
if (ptr) {
AFree(*ptr);
delete ptr;
}
}};
|
All this seems a bit complicated. You're essentially having a pointer to a pointer. I'm wondering if the intention is not to simply have a shared pointer to whatever TypeA is a pointer to. For example, if TypeA is an alias for T* then I suspect what the author really wanted was std::shared_ptr<T>.
1 2 3 4 5 6 7 8
|
void AFree(T*);
T* ACreate();
std::shared_ptr<T> handle_{ACreate(), [](T* ptr) {
if (ptr) {
AFree(ptr);
}
}};
|