Let’s say that DoSomething method is the implementation of an interface. I can’t change its signature. How could DoSomething instantiate MyClass2 with the second constructor and provide a smart pointer to the current instance of MyClass (not a copy) ?
#include <Windows.h>
#include <iostream>
class MyClass;
class MyClass2 {
public:
std::shared_ptr<MyClass> ptr;
MyClass2() {
ptr = nullptr;
}
MyClass2(std::shared_ptr<MyClass> ptrParam) {
ptr = std::move(ptrParam);
}
};
class MyClass {
public:
int value;
MyClass() :
value{1} {
OutputDebugString(L"MyClass\r\n");
}
~MyClass() {
OutputDebugString(L"~MyClass\r\n");
}
std::shared_ptr<MyClass2> DoSomething() {
return std::make_shared<MyClass2>();
}
};
int main() {
auto ptr = std::make_shared<MyClass>();
auto ptr2 = ptr->DoSomething();
}
CodePudding user response:
The only way for this to work is if DoSomething
has access to a smart pointer pointing to the instance of MyClass
. You can't place a shared_ptr
in MyClass
because that would create a reference loop, creating a memory leak.
However, there is another type of smart pointer: weak_ptr
. It was designed for pretty much this purpose: when you need a smart pointer, but you don't want to create a reference loop.
class MyClass {
public:
int value;
std::weak_ptr<MyClass> selfReference;
MyClass() :
value{1} {
OutputDebugString(L"MyClass\r\n");
}
~MyClass() {
OutputDebugString(L"~MyClass\r\n");
}
void giveSelfReference(std::shared_ptr<MyClass>& sr) {
selfReference = sr;
}
std::shared_ptr<MyClass2> DoSomething() {
return std::make_shared<MyClass2>(selfReference.lock());
}
};
So, then main would look like:
int main() {
auto ptr = std::make_shared<MyClass>();
ptr->giveSelfReference(ptr);
auto ptr2 = ptr->DoSomething();
}
Edit: There is a comment recommending std::enable_shared_from_this<T>::shared_from_this
, I'm not familiar with this, but it looks to be a somewhat more elegant version of my solution.