I am trying the figure out a way to use shared_ptr and weak_ptr in my code. I have two classes - Class One and Class Two. Two in an inner class of One. Class two's constructor takes in a weak_ptr of Class One as shown below and stores it for later use.
Class One
{
Class Two
{
private:
std::weak_ptr<One> m_wptrOne;
public:
Two(std::weak_ptr<One> wptrOne)
{
m_wptrOne = wptrOne;
/* m_wptr is used later by class Two if not expired and valid ofcourse */
}
}; // End Class Two
.....
void foo()
{
std::shared_ptr sptrOne(this);
Two obj(sptrOne);
.... /* do my work */
} // Program crashes when foo terminates
}; //End Class One
I get a crash when my function foo returns because I think "sptr" is trying to free "this" pointer thinking that it is the only owner of it.
How can I solve this problem? Or is my program architecturally incorrect? Any suggestion would be greatly appreciated.
Thanks,
Tushar
I don't want to make it compulsory for my library users to create the object on the heap as a shared pointer.
Then your inner class cannot require a weak_ptr. The use of a weak_ptr requires the use of a shared_ptr; it relies on the machinery that shared_ptr creates to know when the pointer has been destroyed. So if you don't want users to have to use shared_ptr, you cannot do anything that expects the class to be wrapped in a shared_ptr. Like create a weak_ptr from it.
Therefore, you need to make your inner class independent of weak_ptr if you want users to be able to not create these objects on the heap.
You could try something where you force users to wrap their stack objects in a shared_ptr that uses a special deleter. But that'd be far more annoying than just heap allocating it.
The below is an example of using enable_shared_from_this to pass weak ownership semantics from this.
Note that it is not possible to express weak ownership semantics to an object with automatic storage duration.
The crash you mention regarding shared_from_this is probably an exception of type std::bad_weak_ptr caused by the attempt to gain a shared_ptr from an object that is not shared.
#include <memory>
class One : public std::enable_shared_from_this<One>
{
public:
class Two
{
private:
std::weak_ptr<One> m_wptrOne;
public:
Two(std::weak_ptr<One> wptrOne)
{
m_wptrOne = wptrOne;
/* m_wptr is used later by class Two if not expired and valid ofcourse */
}
}; // End Class Two
//.....
void foo()
{
std::shared_ptr<One> sptrOne = shared_from_this();
Two obj(sptrOne);
//.... /* do my work */
} // Program crashes when foo terminates
}; //End Class One
int main()
{
auto one = std::make_shared<One>();
one->foo();
}
Related
I'm trying to store references to objects that inherit from a nested abstract base class inside a std::set in the outer class.
Let me show you the code first since I think that's much more clear:
Class.h interface:
#ifndef Class_H_
#define Class_H_
#include <set>
#include <memory>
class Class
{
public:
class AbstractBase;
private:
std::set< std::shared_ptr<AbstractBase>> set;
public:
Class();
~Class();
void add(AbstractBase& object);
};
#endif
Abstract.h interface:
#ifndef ABSTRACT_H_
#define ABSTRACT_H_
#include "Class.h"
class Class::AbstractBase
{
friend class Class;
public:
virtual ~AbstractBase();
private:
virtual void foo(int in) = 0;
};
#endif
Derived.h interface:
#ifndef DERIVED_H_
#define DERIVED_H_
#include "Class.h"
#include "AbstractBase.h"
class Derived : private Class::AbstractBase
{
public:
~Derived() override;
private:
void foo(int in) override;
};
#endif
add.cc implementation:
#include "Class.h"
#include "AbstractBase.h"
void Class::add(AbstractBase& object)
{
// create a shared pointer to object
// and insert it in the set
set.insert(std::make_shared<AbstractBase>(object)); // <-- this is where it fails
}
So I would have multiple different derived objects all inheriting from AbstractBase which need to be stored together in the std::set container.
Compilation fails because of the pure virtual function. At first, I didn't use the std::shared_ptr and thought that this was the reason for failure, I found this SO answer suggesting to use a std::shared_ptr instead. I'm still getting a compilation error in Class::add because AbstractBase::foo is pure, but I thought the std::shared_ptr would solve this?
I found similar questions but nothing that helped me solve my specific problem. Could someone explain to me what I'm doing wrong?
Thank you.
EDIT: Wow! Thanks for the informative answers, I'll need some time to thoroughly understand them all and see what works best for me. I'll update this question once I'm done!
What your function attempts to do is make a copy of an object, allocate a shared instance for the copy, and store pointer to the copy.
Since your intention is to "store references" in the set, you presumably intend to store the objects elsewhere and don't actually want copies. If those referred objects are shared, then the correct solution is to pass the shared pointer:
void Class::add(std::shared_ptr<AbstractBase> ptr)
{
set.insert(std::move(ptr));
}
If the referred objects aren't shared, then you cannot refer to them with a shared pointer. You can use a non-owning pointer instead:
std::set<AbstractBase*> set;
void Class::add(AbstractBase* ptr);
However, be very careful with the non-owning approach to keep the referred objects alive at least as long as they are referred by the set. This is non-trivial. Reference can be used as an argument to add, but I recommend against this, since it may not be obvious to the caller that the function will store pointer to the argument for longer than the functions execution.
If you do want to copy, then you can use a virtual function that returns a shared pointer. Example:
class Class::AbstractBase
{
public:
virtual std::shared_ptr<AbstractBase> copy() = 0;
// ...
class Derived : private Class::AbstractBase
{
public:
std::shared_ptr<AbstractBase> copy() override {
auto ptr = std::make_shared<Derived>(*this);
return {ptr, static_cast<Class::AbstractBase*>(ptr.get())};
}
// ...
void Class::add(AbstractBase& object)
{
set.insert(object.copy());
To avoid repeating the identical copy in multiple derived types, you can use CRTP.
If you want to copy a class of unknown dynamic type, there are three well-known ways to get around having insufficient information:
Have a way to map the object to a handler expecting that specific most-derived type. typeid, a member-function, or a data-member in the common base-class which is its static type is most often used. This costs time, and is cumbersome to set up, but at least you often don't have to modify the class or use fat pointers.
Have a function to .clone() the object in the statically known base. This is known as the virtual constructor idiom, and generally the most efficient and convenient to set up.
Lug around an extra-pointer for cloning. This is the least invasive to the type or regarding additional setup, but changes the interfaces.
Which is most appropriate is yours to decide.
That is, if you actually want to copy the object, and shouldn't have passed a shared_ptr to .add() instead.
You need to clarify the ownership of the objects stored in the set. If you use std::shared_ptr, you fundamentally encode that the set inside each Class owns the contained instances. This is incompatible with an add(AbstractBase&) method - you cannot really take ownership of an arbitrary object by reference. What if this object is already managed by a different shared_ptr?
Maybe you actually only want to store copies in the set. In that case, see the other answer(s) for ways to polymorphically copy ("clone") objects.
It is also open why you want to use std::set. std::set establishes uniqueness of the contained objects using the < operator (or a user-provided comparison functor with equivalent semantics). Do you even want uniqueness? If so, based on what criteria? Currently, there is no way to compare the stored class objects. std::shared_ptr "solves" that problem by instead comparing the internal pointer values, but I doubt that's what you need here.
If you actually want to store and compare objects solely based on their memory locations and not assume ownership of the stored objects, you could just use raw pointers. If you only want to store a whole bunch of objects without caring about uniqueness (since you currently attempt to create copies, each stored element would have a unique address and thus you currently would never use that aspect of std::set), maybe std::vector is the better solution. std::set may also help with determining whether an object is present in the collection efficiently, but std::vector can do that just the same (and possibly faster, if you sort and binary search). Consider the advice in http://lafstern.org/matt/col1.pdf.
Basically i have a one struct that contains objects to share between classes as following;
struct CoreComponents
{
std::unique_ptr<a> m_A = std::make_unique<a>();
std::unique_ptr<b> m_B;
std::unique_ptr<c> m_C = std::make_unique<c>();
};
And in my main class i own it via unique_ptr;
class Game
{
...
private:
std::unique_ptr<CoreComponents> m_Components;
...
};
Then i have other n classes which i need to access that m_Components object from it's functions without creating copies. (i will not modify contents of that object)
I tried using shared_ptr to hold m_Components in Game class then pass it to other classes (to their constructors) via value and store it but that scenario causes memory leaks. (i use memcheck for checking leaks) I found out that it's the cause of the leak but i couldn't figure out why exactly.
Shared_ptr scenario
Constructor of class which i need to access CoreComponents object;
GameScene::GameScene(std::shared_ptr<CoreComponents> components)
: m_Components(std::move(components))
I'm trying to hold it as member of GameScene class then use it in functions;
std::shared_ptr<CoreComponents> m_Components;
And this is how i pass it from inside of the Game class;
auto gs = std::make_unique<GameScene>(m_Components)
General usage inside GameScene class;
m_Components->m_A->draw(*m_OtherObjectInsideGameScene);
So what is the best way to create similar design using modern c++?
I was trying to avoid Singleton pattern but do i have to use it to achieve this or it's possible with better smart pointer usage?
PS: CoreComponents struct needs to be deleted from memory when Game class is destroyed.
It seems that you correctly separate the concerns of ownership and usage. The only trouble you have is how to forward the components to the rest of your system.
I would keep your owning structure, and create dedicated structures for the specific users:
struct CoreComponents {
unique_ptr<A> a; unique_ptr<B> b; ...
};
struct PartOfTheSystem {
void use(A& a, B& b);
};
struct Game {
CoreComponents components;
PartOfTheSystem user;
void stuff() {
user.use(*components.a, *components.b);
}
};
Yes: more typing.
But also: very clear logic: construction/ownership and use are separate concerns, and this is perfectly clear by design! Also refer to https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-smartptrparam.
The best way if you have shared objects is indeed to use a shared_ptr.
A unique_ptr is for unique ownership.
If you had memory leaks, it's time to investigate why that was, and fix them! Your report suggests a cyclical reference. Check for accidental lambda capture, and in some places you perhaps meant to use weak_ptr instead.
Using a singleton for this is like fixing your car's broken tyre by setting the whole thing on fire and taking a donkey instead. Your unique_ptr approach is more like fixing your car's broken tyre by removing it and driving on rims for the lols.
I have a class MyClass that should be able to return this wrapped in QSharedPointer<MyClass>.
It is my understanding (and experience) that simply creating new instances of QSharedPointer<MyClass>(this) is NOT the way to go. Instead The correct way to accomplish what I want is to let MyClass inherit from QEnableSharedFromThis<MyClass> to provide the member function sharedFromThis().
This member function should return this wrapped in QSharedPointer<MyClass> without all the bad side effects that would otherwise occur.
class MyClass : public QEnableSharedFromThis<MyClass>
{
/* ... */
public:
void testSharedThis()
{
auto sp=QEnableSharedFromThis<MyClass>::sharedFromThis();
if(sp.isNull()){
qWarning()<<"SHARED POINTER TO *this* WAS NULL!";
}
}
};
void main(){
MyClass *mc=new MyClass;
mc->testSharedThis();
}
However when I run testSharedThis() in the example above, sharedFromThis() always returns nullptr instead of this wrapped in QSharedPointer<MyClass>.
I am new to QEnableSharedFromThis and I am wondering if there is something that I am missing, or what could be the cause of this?
According to the official documentation:
A base class that allows obtaining a QSharedPointer for an object already managed by a shared pointer. You can inherit this class when you need to create a QSharedPointer from any instance of a class; for instance, from within the object itself.
So you need to instantiate your pointer as smart pointer:
QSharedPointer<MyClass> mc(new MyClass());
mc->testSharedThis();
Or in your case use the equivalent to std::make_shared for Qt Smart Pointers:
QSharedPointer<MyClass> mc = QSharedPointer<MyClass>::create();
mc->testSharedThis();
OK, I started using shared-pointers and pass shared-pointers as much as possible. No conversion to raw pointers anymore. This works good, except in this specific case:
Suppose we have a class that also is an observer on another class, like this:
class MyClass : public IObserver
{
public:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
std::shared_ptr<SomeOtherClass> m_otherClass;
};
This class is used like this in my application:
std::shared_ptr<MyClass> myInstance(new MyClass(otherInstance));
...
myInstance->DoSomethingImportant();
MyClass gets a shared-pointer to another class and stores this in its m_otherClass data member.
In the DoSomethingImportant method, the MyClass instance does lots of important things, including registering itself as an observer on m_otherClass, like this:
m_otherClass->registerObserver(this);
The problem is that the registerObserver method is defined like this:
void registerObserver (std::shared_ptr observer);
It expects a shared pointer, but 'this' is a raw pointer, not a shared one.
I see three ways of solving this:
Find a trick to convert a normal pointer to a shared pointer (see question convert pointer to shared_ptr), but the answers to that question only suggest to copy the shared-pointers, not on how to actually convert the pointer to a shared pointer.
Pass the shared-pointer to ourself to the method, like this: "myInstance->DoSomethingImportant(myInstance);" which seems a bit stupid.
Put the observer part into a separate class. This looks like some overkill, and might make the class harder to understand.
This problem makes it obvious that shared-pointers are just an add-on to C++ (I don't think you have the same problem in other languages/environments like C# (or .Net in general) and Java).
Any other suggestions or tricks on how to handle this situation?
What you need is probably the enable_shared_from_this and shared_from_this facilities. The docs are here
Note that you cannot use shared_from_this until the constructor has fully completed and the object is already owned by another shared_ptr.
struct test : boost::enabled_shared_from_this<test>
{
test() {
// shared_from_this(this); // error, still not owned by another shared_ptr
}
boost::shared_ptr<test> shared() {
return shared_from_this(this);
}
};
int main() {
test * t = new test;
// boost::shared_ptr<test> p = t->shared(); // error, not yet owned by other shared_ptr
boost::shared_ptr<test> owner( t );
boost::shared_ptr<test> p = t->shared(); // [*] ok, "owner" owns the object
}
[*] This part of the example is silly, you could just copy owner into p, instead of calling the method. It is just presented to note when it is ok or not to called shared_from_this inside the test methods.
For observer pattern, the observed object doesn't take the ownership of the observer, why not just using a raw pointer? The life cycle of the observer should be controlled by observer itself.
By using enable_shared_from_this, you introduce cycle dependency for the observer and its observed object. That means if not delete explicitly, the resource will never be released.
How about making the constructor private and having a static construction method like this:
class MyClass : public IObserver
{
public:
static std::shared_ptr<MyClass> createObserver(std::shared_ptr<SomeOtherClass> otherClass);
void DoSomethingImportant();
private:
MyClass (std::shared_ptr<SomeOtherClass> otherClass);
std::shared_ptr<SomeOtherClass> m_otherClass;
};
Then you could instantiate the observer cleanly in the static method and not have to worry about the this pointer at all.
Can you move the registration step into a seperate method? :
shared_ptr<SomeOtherClass> other(new SomeOtherClass());
shared_ptr<MyClass> my(new MyClass());
// register myself to the observer
other->registerObserver(my);
my->DoSomethingImportant();
A good design of observer pattern can be implemented with boost::signal and boost::bind
libraries. I encourage you to have a look.
Best Regards,
Marcin
I've been looking at the example C++ Factory method pattern at Wikipedia and have a couple of questions:
Since the factory method is static, does that mean the newly created object won't go out of scope and have the destructor method called when the factory method exits?
Why return a pointer, as opposed to a reference? Is it strictly a matter of preference, or is the some important reason for this?
Edit 1: The more I think about it, both the reference and the pointer returned will stay in scope because they are referenced outside of the method. Therefore, the destructor won't be called on either one. So it's a matter of preference. No?
Edit 2: I printed out the destructor call on the returned reference, and it doesn't print until the program exits. So, barring further feedback, I'm going to go with the reference for now. Just so I can use the "." operator on the returned object.
Static method is one that can be called without having an instance of the factory. That has nothing to deal wtih the lifetime of the newly created object. You could use a non-static method with the same success. The factory method usually doesn't need any data from an existing object of the same class and therefor doesn't need an existing instance and this is why factorey methods are usually static.
You will use new to create the object that the factory will return. It's usual to return them by pointer. This shows explicitly that it's a new object ant the caller must take care of its lifetime.
I'm thinking there is a greater issue of understanding memory management. The factory method is allocating items on the heap (using new). Items on the heap never get automatically reclaimed (except by modern desktop OSs on process termination). The behavior you are describing is for items on the stack where they are reclaimed when you leave the local scope.
If you return a reference to an object that reference will become invalid when the method goes out of scope. This won't happen with a pointer, since the destructor isn't called.
It is true that static modifies when the value goes out of scope, but only if the variable is declared static, not if the method is declared static.
Your Wiki link says wrong.
There shouldn't be any static method. You can consider Factory Method as Template Method pattern that creates Objects. This method doesn't receive any "Name" parameter and create all the time same type of object.
Often, designs start out using Factory
Method (less complicated, more
customizable, subclasses proliferate)
and evolve toward Abstract Factory,
Prototype, or Builder (more flexible,
more complex) as the designer
discovers where more flexibility is
needed. [GoF, p136]
In the following example Business::makeObject is the factory method
class ObjectBase
{
public:
virtual void action() = 0;
virtual ~ObjectBase(){};
};
class ObjectFirst : public ObjectBase
{
public:
virtual void action(){ std::cout << "First"; }
};
class ObjectSecond : public ObjectBase
{
public:
virtual void action(){ std::cout << "Second"; }
};
class Business
{
public:
void SendReport()
{
std::auto_ptr< ObjectBase > object(makeObject());
object->action();
}
virtual ~Business() { }
protected:
virtual ObjectBase* makeObject() = 0;
};
class BusinessOne: public Business
{
public:
protected:
virtual ObjectBase* makeObject()
{
return new ObjectFirst();
}
};
class BusinessTwo: public Business
{
public:
protected:
virtual ObjectBase* makeObject()
{
return new ObjectSecond();
}
};
int main()
{
std::auto_ptr<Business> business( new BusinessTwo() );
business->SendReport();
return 0;
}
No. Static method - is almost same as global function in class namesapce and with access to private static variables;
Pointers usage is issue of createing objects in heap. They create object in heap for longer object lifetime than create-function scope;
EDIT:
I think wikipedia - is wrong in c++ example.
We have in exmaple - not same implementation as in class diagram or here (http://www.apwebco.com/gofpatterns/creational/FactoryMethod.html)
It will be better if you read about patterns from most trusted sources, e.g: Design Patterns: Elements of Reusable Object-Oriented Software.
The keyword static means different things on a method and on a variable. On a method as in the example it means that it is class global, and you need not have an instance of the class to call it.
To create a new object dynamically you need to use new, or 'a trick' is to assign a temporary object to a reference. assigning a temporary object to a point will not keep that object alive.
So you could do the following, but it is not normally done because you would often want to keep many things created from a factory, and then you would have to copy them rather than simply holding the pointer in a list.
class PizzaFactory {
public:
static Pizza& create_pizza(const std::string& type) {
if (type == "Ham and Mushroom")
return HamAndMushroomPizza();
else if (type == "Hawaiian")
return HawaiianPizza();
else
return DeluxePizza();
}
};
const Pizza &one = create_pizza(""); // by ref
Pizza two = create_pizza(""); // copied
EDIT
Sorry mistake in code - added missing const to ref.
Normally, a temporary object lasts only until the end of the full expression in which it appears. However, C++ deliberately specifies that binding a temporary object to a reference to const on the stack lengthens the lifetime of the temporary to the lifetime of the reference itself