I'm attempting to create an accessor for a class member variable using smart pointers. Here's the code:
class MyResource
{
};
class MyClass
{
public:
std::unique_ptr<MyResource> getResource();
private:
std::unique_ptr<MyResource> resource;
};
std::unique_ptr<MyResource> MyClass::getResource()
{
return this->resource;
}
The error I get trying to compile this:
cannot access private member declared in class 'std::unique_ptr<_Ty>'
Adding .get
to this->resource
of course doesn't work because the return type changes.
Should I not be using a unique_ptr here? Is this just a syntax issue? Am I totally on the wrong track?
my background with smart pointers: I've been using plain-old-pointers for a couple of years now in part because I can't find a solid explanation of when to use which types of smart pointers and how to go about using them. I'm tired of making excuses, so I'm just diving in. I think I understand what smart pointers are and why to use them, but I understand very little of the details. At the moment I'm totally lost in the endless Q&A about smart pointers.
Return smart pointers from functions You should follow the same logic above: return smart pointers if the caller wants to manipulate the smart pointer itself, return raw pointers/references if the caller just needs a handle to the underlying object.
So the best way to return a shared_ptr is to simply return by value: shared_ptr<T> Foo() { return shared_ptr<T>(/* acquire something */); }; This is a dead-obvious RVO opportunity for modern C++ compilers.
There is an implicit conversion from shared_ptr to weak_ptr ; returning a shared_ptr from a function whose return type is weak_ptr will just call the conversion.
To make use of smart pointers in a program, you will need to include the <memory> header file. Smart pointers perform automatic memory management by tracking references to the underlying object and then automatically deleting that object when the last smart pointer that refers to that object goes away.
The most important thing to understand about smart pointers is that the "pointer" aspect is not the fundamental part of their semantics. Smart pointers exist to represent ownership. Ownership is defined as the responsibility for cleanup.
A unique pointer says: "I am the sole owner of the pointee. I will destroy it when I go out of scope."
A shared pointer says: "I am one of a group of friends who share the responsibility for the pointee. The last of us to go out of scope will destroy it."
(In a modern C++ program,) A raw pointer or reference says: "I do not own the pointee, I merely observe it. Someone else is responsible for destroying it."
In your case, using a unique_ptr
for the member type means that MyClass
owns the MyResource
object. If the getter is supposed to transfer ownership (that is, if the MyClass
is giving up the resource to whoever called the getter), returning a unique_ptr
is appropriate (and you'll have to return std::move(resource);
to make the ownership transfer explicit).
If the getter is not supposed to give up the ownership (which I consider the likely scenario), just return a plain old pointer (if returning a null pointer is an option) or a plain old reference (if returning null is not an option).
You have several options here, depending on the semantics you wish your class to observe.
You want to give up ownership of your resource:
std::unique_ptr<MyResource> MyClass::releaseResource() {
return std::move(this->resource);
}
You want to maintain unique ownership, but have somebody else use it:
MyResource& MyClass::getResource() {
assert(this->resource);
return *(this->resource);
}
You want to share ownership, so the resource doesn't get destroyed if MyClass
goes out of scope: switch everything to std::shared_ptr<MyResource>
and still return by value.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With