Store weak pointer to self - c++

I work with a codebase that was partially implemented by someone who was in love with overly complex solutions to simple problems (e.g. template classes with two parameters that were only ever instantiated for one pair of types). One thing she did was to create objects in a smart pointer, and then have the object store a weak pointer to itself.
class MyClass {
//...
boost::weak_ptr<MyClass> m_self;
//...
};
boost::shared_ptr<MyClass>
Factory::Factory::Factory::CreateMyClass() {
boost::shared_ptr<MyClass> obj(new MyClass(...));
boost::weak_ptr<MyClass> p(obj);
obj->storeSelfPointer(p);
return obj;
}
The class then proceeds to use m_self by locking it and passing around the resulting shared pointer.
For the life of me, I cannot fathom what she was trying to accomplish. Is there some pattern or idea that would explain this implementation? It looks to me like this is completely pointless and I'd like to refactor it away.
EDIT: I should mention that none of the places that use the resulting smart pointer obtained from locking m_self actually retain the smart pointer.

A possible use of this "design" could be to use m_self.lock() to generate shared pointers from this.
If you remove this weak pointer member, the reference count hold by the generated shared pointer from this would be incorrect.
It achieves the same than std::enable_shared_from_this, interestingly enough, cppreference.com mentions this design :
A common implementation for enable_shared_from_this is to hold a weak
reference (such as std::weak_ptr) to this. The constructors of
std::shared_ptr detect the presence of an enable_shared_from_this base
and assign the newly created std::shared_ptr to the internally stored
weak reference
And the C++ standard, section § 20.8.2.4 10 , mention the same possible implementation :
The shared_ptr constructors that create unique pointers can detect the
presence of an enable_shared_- from_this base and assign the newly
created shared_ptr to its
__weak_this member
Possible Refactoring :
If you are using C++11, you can remove the std::weak_ptr member, and publicly inherits from std::enable_shared_from_this<T>. You should retrieve a shared pointer from this by calling shared_from_this().
If you are not using C++11 but can use boost, use boost::enable_shared_from_this, see the boost documentation. You should retrieve a shared pointer from this by calling shared_from_this().
If you are not using C++11, and can't use boost, you can bring the proposed implementation of the standard to your code base, it is short enough :
Code : (copied from § 20.8.2.4 - 11, remove leading underscores, and you probably want to rename it)
template<class T> class enable_shared_from_this {
private:
weak_ptr<T> __weak_this;
protected:
constexpr enable_shared_from_this() : __weak_this() { }
enable_shared_from_this(enable_shared_from_this const &) { }
enable_shared_from_this& operator=(enable_shared_from_this const &) { return *this; }
~enable_shared_from_this() { }
public:
shared_ptr<T> shared_from_this() { return shared_ptr<T>(__weak_this); }
shared_ptr<T const> shared_from_this() const { return shared_ptr<T const>(__weak_this); }
};
And use shared_from_this() to make a shared pointer. If you do copy this code, note that constructing shared pointers from this by other means would not work. The shared pointers constructors need to be modified (as explain by the standard quote above).

Related

is C++ raw pointer used to initialise a shared pointer invalidated when the shared pointer goes out of scope? [duplicate]

I have functions that take in std::shared_ptr as an argument so I am forced to use std::shared_ptr, but the object I am passing to the function is not dynamically allocated. How do I wrap the object in std::shared_ptr and have std::shared_ptr not call delete on it.
MyType t;
nasty_function(std::shared_ptr<MyType>(&t, [](MyType*){}));
Specify a no-op deleter when creating the shared pointer. E.g. like this:
void null_deleter(MyType *) {}
int main()
{
MyType t;
nasty_function(std::shared_ptr<MyType>(&t, &null_deleter));
}
The best way to do this is to use the aliasing constructor:
nasty_function(std::shared_ptr<MyType>(std::shared_ptr<MyType>{}, &t));
Compared to the null deleter approach, this doesn't need to allocate a control block, and is noexcept.
As noted by #Casey and #Nevin, this should only be done when you are sure that the function won't attempt to take shared ownership, or if the object would outlive everything that might "own" it.
Boost.Core provides a null_deleter function object exactly for this purpose.
Citing the documentation:
The header <boost/core/null_deleter.hpp> defines the boost::null_deleter function object, which can be used as a deleter with smart pointers such as unique_ptr or shared_ptr. The deleter doesn't do anything with the pointer provided upon deallocation, which makes it useful when the pointed object is deallocated elsewhere.
Example from the documentation:
std::shared_ptr< std::ostream > make_stream()
{
return std::shared_ptr< std::ostream >(&std::cout, boost::null_deleter());
}
You can do this trick:
A a;
shared_ptr<A> pa(&a);
foo(pa);
new (&pa) shared_ptr<A>(); // pa "forgets" about a
i was just searching for a solution, saw this question. found nothing and made a great one this is my code
class HBitmap : public shared_ptr<HBITMAP__>
{
public:
HBitmap();
HBitmap(HBITMAP Handle);
bool autoDelete = true;
};
Win32::HBitmap::HBitmap(HBITMAP Handle)
: shared_ptr<HBITMAP__>(Handle, [&](HBITMAP hBitmap) {if(autoDelete)DeleteObject(hBitmap);})
{
}
this solution is a combination of lambda expressions and inheritance.
very well formed. fast. you can't expect anything more. not only you can set the deleter, but if you do some modifications, you can use a std::function<void(pointer)> as a custom deleter. with lambdas you can run free and do what ever you want.

How to use a shared_ptr with a pointer to struct that should not be freed

Currently I'm using some functions from the glib library. With glib also comes the gio. glib is a C library and therefore I need to delete some structures that I create.
for many of the objects I create a smartpointer eg:
std::shared_ptr<GAsyncQueue> my_queue = std::shared_ptr<GAsyncQueue>(g_async_queue_create(), g_async_queue_unref);
For this creates a shared pointer to an GAsyncQueue and this is safely destroys the queue on its end of its life.
However, I encounter a problem when I obtain a pointer from the gio library that I should not free. In the following code my_connection is a GSocketClient which implements (in glib speak) GIOStream.
std::shared_ptr<GInputStream> my_input_stream =
std::shared_ptr<GInputStream> (
g_io_stream_get_input_stream(G_IO_STREAM(my_connection.get()))
);
Because the documentation on GIOStream mentions, that the pointer obtained with g_io_stream_get_input_stream() should not be freed. That is because it is owned by the my_connection instance.
I thought about creating a lamda for the destroy object, the second parameter of a shared pointer object. eg auto deleter = [](GInputStream* ptr) {}; and then give that lambda as destroy function to the shared pointer, but that feels a kind of stupid.
Well, alternative to no-op deleter might be using aliasing shared pointer
template <class U> shared_ptr (const shared_ptr<U>& x, element_type* p) noexcept;
It shares x, but after get() you'll get back p.
Discussion: What is shared_ptr's aliasing constructor for?
You probably just don't need a std::shared_ptr. And you probably don't even need a pointer.
As I read your question and comments, I don't see any point against
auto& my_input_stream = *( g_io_stream_get_input_stream(G_IO_STREAM(my_connection.get())) )
It is true that pointers allow optional data. However, it's also true that it's mostly used the wrong way. Having
void foo( type* ptr)
{
if (!ptr)
throw exception;
}
often doesn't make sense. If the function has to to work on concrete data, allowing a NULL parameter is only useful if you then worry about providing that data. Otherwise, just require a reference (possibly const) to the object.
Smart pointers are useful; but they're still pointers. Avoiding them altogether, if possible, is even better.
From the comments:
However, a reference must always be initialized
Absolutely. Since C++11 though we've got std::reference_wrapper which can also be reassinged and stored in containers.
You can use a deleter type that does nothing, but it will need to be passed as an argument to the shared_ptr's constructor
struct DoNothing {
template <typename T>
void operator()(T*) const noexcept { }
};
When creating a shared_ptr you will need to create one of these deleters and pass it in the constructor (as you're doing with the lambda). You can make this easier on yourself with an intermediate function
template <typename T>
std::shared_ptr<T> non_deleting_shared_ptr(T* ptr) {
return {ptr, DoNothing};
}
auto my_input_stream =
non_deleting_shared_ptr(
g_io_stream_get_input_stream(G_IO_STREAM(my_connection.get()));
However the bigger question is why you're using smart pointers when you don't want ownership to be a part of it. You'd almost certainly be better off with just a GAsyncQueue*, unless of course you're in a situation where you have a shared_ptr that needs to free sometimes. Like a data member maybe?

C++ Rule of Zero : polymorphic deletion and unique_ptr behavior

In the recent overload journal under the topic Enforcing the rule of zero, the authors describe how we can avoid writing the Rule of five operators as the reasons for writing them are:
Resource management
Polymorphic deletion
And both these can be taken care of by using smart pointers.
Here I am specifically interested in the second part.
Consider the following code snippet:
class Base
{
public:
virtual void Fun() = 0;
};
class Derived : public Base
{
public:
~Derived()
{
cout << "Derived::~Derived\n";
}
void Fun()
{
cout << "Derived::Fun\n";
}
};
int main()
{
shared_ptr<Base> pB = make_shared<Derived>();
pB->Fun();
}
In this case, as the authors of the article explain, we get polymorphic deletion by using a shared pointer, and this does work.
But if I replace the shared_ptr with a unique_ptr, I am no longer able to observe the polymorphic deletion.
Now my question is, why are these two behaviors different? Why does shared_ptr take care of polymorphic deletion while unique_ptr doesn't?
You have your answer here: https://stackoverflow.com/a/22861890/2007142
Quote:
Once the last referring shared_ptr goes out of scope or is reset, ~Derived() will be called and the memory released. Therefore, you don't need to make ~Base() virtual. unique_ptr<Base> and make_unique<Derived> do not provide this feature, because they don't provide the mechanics of shared_ptr with respect to the deleter, because unique pointer is much simpler and aims for the lowest overhead and thus is not storing the extra function pointer needed for the deleter.
It'll work if you use the C++14 make_unique or write your own one like in Yakk's answer. Basically the difference between the shared pointer behavior is that you got:
template<
class T,
class Deleter = std::default_delete<T>
> class unique_ptr;
for unique_pointer and as you can see, the deleter belongs to the type. If you declare a unique_pointer<Base> it'll always use std::default_delete<Base> as default. But make_unique will take care of using the correct deleter for your class.
When using shared_ptr you got:
template< class Y, class Deleter >
shared_ptr( Y* ptr, Deleter d );
and other overloads as constructor. As you can see the default deleter for unique_ptr depends on the template parameter when declaring the type (unless you use make_unique) whilst for shared_ptr the deleter depends on the type passed to the constructor.
You can see a version that allows polymorphic delete without virtual destructor here (this version should also work in VS2012). Note that it is quite a bit hacked together and I'm currently not sure what the behavior of unique_ptr and make_shared in C++14 will be like, but I hope they'll make this easier. Maybe I'll look into the papers for the C++14 additions and see if something changed if I got the time later.
template<typename T>
using smart_unique_ptr=std::unique_ptr<T,void(*)(void*)>;
template<class T, class...Args> smart_unique_ptr<T> make_smart_unique(Args&&...args) {
return {new T(std::forward<Args>(args)...), [](void*t){delete (T*)t;}};
}
The problem is that the default deleter for unique_ptr calls delete on the stored pointer. The above stores a deleter that knows the type at construction, so when copied to base class unique_ptr will still delete as the child.
This adds modest overhead, as we have to dereference a pointer. In addition it denormalizes the type, as default constructed smart_unique_ptrs are now illegal. You can fix this with some extra work (replace a raw function pointer with a semi smart functor that at least does not crash: the function pointer, however, should be asserted to exist if the unique is non-empty when the deleter is invoked).

smart pointer array

I have created a smart pointer class like:
template <class T>
class Owner
{
T* m_p;
public:
Owner(T *p=0) : m_p(p) {}
~Owner() { if (m_p) delete m_p; }
T* operator ->() { return m_p; }
T& operator *() { return *m_p; }
// other members.
};
It works well (resembles to the auto_ptr in boost library), but now I have the requirements that I want to store an dynamic array of smart pointers in an obj, and it must support:
1) insert new smart pointer into the smart pointers array to let the array resize and acquire the ownership of the new obj,
2) delete one smart pointer on the fly and the resource get freed,
3) when finalizing the array, all objects get deleted.
I was thinking using std::vector<Owner<T> >, but seems c++ best practice suggests not storing smart pointers in std containers, because copy/assignment behaviors, so what other things can I employ to implement this? something like the OwnerArr in the below example:
class Adapter;
class Computer
{
public:
Computer() {}
~Computer() { // adapters get freed automatically here. }
void insertAdapter(Adapter* pAdapter) { m_adapters->appendOne(pAdapter); }
OwnerArr<Adapter> m_adapters;
};
Thanks in advance!
You can't store your Owner, or std::auto_ptr (which you shouldn't use anyway, since it's deprecated), in a standard container because they are not really copyable.
In C++11, there's std::unique_ptr: a single-ownership smart pointer to replace auto_ptr, which is movable but not copyable. This can be moved or emplaced into any container, as long as you don't need to do anything that involves copying it. If you need multiple pointers to share ownership of the same object, then you can use std::shared_ptr instead.
If you're stuck with an older language version for some reason, then Boost can give you smart pointers, including a shared_ptr very similar to the standard one, or pointer containers similar to your OwnerArray.
If you do decide to roll your own resource management classes, always remember the Rule of Three. The classes you show have implicitly generated copy constructors and copy-assignment operators which can cause two pointers to own - and try to delete - the same object, which is very bad. You need to either prevent copying (by deleting these functions, or (pre-2011) declaring them private with no implementation), or implement some kind of safe copy semantics.

Smart pointer that does transfer of ownership and is not shared when C++11 is not an option

Currently I am solving my problem with boost::shared_ptr but the semantics is not quite right, since I am "transplanting" members from one object to another. I was looking through this list but it didn't yield too much. Same goes for my brief google searches.
Essentially I am looking for a unique_ptr implementation that works with my gcc4.2 (Hence the restriction to not use C++11)
You could stick with std::auto_ptr until Boost implements unique_ptr on top of the new Boost Move library (C++03 compatible).
See this mailing list traffic d.d. November 10th 2011: http://boost.2283326.n4.nabble.com/smart-ptr-Inclusion-of-unique-ptr-td4021667.html
Edit And Boost Interprocess has a uniqe_ptr<> class template floating around:
http://www.boost.org/doc/libs/1_48_0/doc/html/boost/interprocess/unique_ptr.html
Depending on what exactly you want, you might consider using boost::scoped_ptr. It is very similar to std::unique_ptr, but it cannot be moved (because C++03 doesn't know about move-semantics). It can, however be swapped. So, when you want to transfer ownership, just do this:
boost::scoped_ptr<T> dummy;
dummy.swap(my_ptr);
// now you have basically transferred ownership from my_ptr to dummy
Use std::auto_ptr<..>, it has exactly what you need.
llvm::OwningPtr - it has take method to take ownership.
boost::shared_ptr with custom deleter.
This is something I used in unit test to simulate Corba _var class behaviour.
struct CondDel {
bool doDel;
CondDel() : doDel(true) {
}
template<typename T>
void operator()(T* p) {
if (doDel)
delete p;
}
};
class MyCorbaObj_var : public boost::shared_ptr<_objref_MyCorbaObj> {
public:
MyCorbaObj_var(_objref_MyCorbaObj* p) : boost::shared_ptr<_objref_MyCorbaObj>(p, CondDel()) {
}
_objref_MyCorbaObj* _retn() {
CondDel* cd = (CondDel*)_internal_get_deleter(typeid(CondDel));
cd->doDel = false;
return get();
}
};
If you want copying objects of your class to make new copies of the pointed-to items, then no kind of pointer (auto_ptr, shared_ptr or naked pointer) will do what you want without some extra work on your part. You will need to manage the copying yourself. Be sure you implement a copy constructor and assignment operator so that they clone the pointed-to items and store the new pointers in the destination object. If you do this, auto_ptr and shared_ptr will both work just fine for you.