Missing shared_ref - c++

While working with std::shared_ptr a lot I kind of miss a shared_ref implementation. That is a specialization of shared_ptr, which guarantees, that it never wraps a nullptr (given right usage, of course).
I kind of wonder why it is not in the C++11 standard. Are there any mayor problems when implementing it? On the top of my head I cannot think of any.
EDIT:
I would expect to have an interface similar to:
template <typename T>
class shared_ref {
public:
shared_ref( T&& ref );
T& get();
T* operator&() const;
template< class Y >
void reset( Y&& obj );
long use_count() const;
bool unique() const;
void swap( shared_ref& r );
};

Are there any mayor problems when implementing it?
Here's one: you can't take ownership of a reference. The whole point of a smart pointer is to claim ownership of the pointer itself. shared_ref can't work because you can't control the lifetime of a reference.
And no, this isn't going to fly either:
shared_ref( T&& ref ) : p(&ref) {}
The user may have given you a stack variable, which now means you have "shared" ownership between this object and a stack variable. And stack variables cannot share ownership with something.
You can only control the lifetime of a pointer. And pointers can be NULL. Therefore, the only thing you can do is a runtime check to see if a pointer is NULL.
The absolute best you can do is an interface equivalent to shared_ptr except that it has no default constructor and throws in the event of being given NULL. Is that really worth creating a whole new pointer type over?
The C++ Core Guidelines support library has the not_null template, which can be applied to most pointer-like types. So you can use not_null<shared_ptr> when you want to verify that a pointer isn't NULL, but only once when it enters use. After the initial creating of the pointer, it doesn't need to check again.
Granted, you can't force other people to use them, but use of the type consistently will resolve the issue.

There are only two ways for a shared_ptr to be null - either it was default constructed, or it was assigned a null value at some point. Since you already agree it doesn't make sense to default construct your hypothetical shared_ref class, that leaves only the second condition.
If you tried to assign a nullptr to your shared_ref object, what would you expect to happen? Should it throw an error? It's trivial to do the same thing with a regular shared_ptr using a simple template function:
template<typename T>
T* notnull(T* ptr)
{
if (ptr == std::nullptr)
throw std::invalid_argument(std::string("nullptr"));
return ptr;
}
std::shared_ptr<int> pint = notnull(GetIntPtr());
Generally things aren't added to the standard unless there's a compelling need with no easy workarounds.

Related

Mix boost::optional and std::unique_ptr

I admit it: I'm in love with the concept of optional. The quality of my code has improved so much ever since I discovered it. Making it explicit whether a variable may or may not be valid is so much better than plain error codes and in-band signaling. It also allows me to not worry about having to read the contract in the documentation, or worrying about whether it's up-to-date: the code itself is the contract.
That said, sometimes I need to deal with std::unique_ptr. Objects of this type might be null or not; at a given point in the code is impossible to know whether the std::unique_ptr is supposed to have a value or not; it's impossible to know the contract from the code.
I would like to somehow mix optional (maybe withboost::optional) and std::unique_ptr, so that I have a dynamically allocated object with scope-destruction and proper copy/move behaviour that explicitly states that it may not have a value. That way, I can use this new type to make it explicit that a check for value is necessary and avoid unnecessary checks for plain std::unique_ptr.
Is there a tool for this inside the C++11 standard, boost or a popular enough library? I could accept defining my own class for this, but that would be the least preferred method (due to lack of thorough testing).
So to recap your question, you want:
A non-optional type that is allocated by value/on the stack: You are happy directly using the object type for this.
An optional type that is allocated by value/on the stack: You are happy using boost::optional for this (or you can use std::optional from C++17).
A non-optional type that is allocated on the heap and owns the pointed-to object.
An optional type that is allocated on the heap and owns the pointed-to object.
You are unhappy that you can express the difference between 1 and 2, but both 3 and 4 usually use the same type (std::unique_ptr). You suggest using std::unique_ptr for 3, never allowing nullptr, and some other thing for 4, but want to know what you can use. (In the comments you also accept the possibility of using std::unique_ptr with nullptr for 4 if something else can be found for 3.)
Literal answer to your question: you can simply use boost::optional<std::unique_ptr<T>> for 4 (while using a bare unique_ptr for 3 as you suggested).
Alternative literal answer to your question: As #StoryTeller said, you could define your own smart pointer type that is like unique_ptr but disallows nullptr, and use that for 3. A quicker (but very dirty) alternative is to force functions to return a pair of both a unique_ptr and a reference to that same object. Then only access the result through the reference, but only do so while the unique_ptr still exists:
template<class T>
using RefAndPtr = std::pair<T&, std::unique_ptr<T>>;
RefAndPtr<Foo> getFoo()
{
std::unique_ptr<Foo> result = std::make_unique<Foo>();
return RefAndPtr<Foo>(*result, std::move(result));
}
My actual suggestion: Just suck it up and use std::unique_ptr for both 3 and 4. Clarifying your intentions in the type system is a good thing, but too much of a good thing can be bad. Using either of the above options is just going to confuse the hell out of anyone that reads your code. And even if you stop people from incorrectly passing around nullptr, what's to stop them passing a pointer around to the wrong object, or already-freed memory, etc.? At some point you have to specify things outside of the type system.
std::unique_ptr is nullable. It becomes null whenever moved-from, or when default constructed.
std::unique_ptr is your nullable heap allocated object.
A value_ptr can be written that is not nullable. Note that there are extra costs at move:
template<class T>
class value_ptr {
struct ctor_key_token{ explicit ctor_key_token(int){} };
public:
template<class A0, class...Args, class dA0 = std::decay_t<A0>,
std::enable_if_t<!std::is_same<dA0, ctor_key_token>{} && !std::is_same<dA0, value_ptr>{}, int> = 0
>
value_ptr( A0&& a0, Args&&... args):
value_ptr( ctor_key_token(0), std::forward<A0>(a0), std::forward<Args>(args)... )
{}
value_ptr(): value_ptr( ctor_key_token(0) ) {}
template<class X, class...Args>
value_ptr( std::initializer_list<X> il, Args&&... args ):
value_ptr( ctor_key_token(0), il, std::forward<Args>(args)... )
{}
value_ptr( value_ptr const& o ):
value_ptr( ctor_key_token(0), *o.state )
{}
value_ptr( value_ptr&& o ):
value_ptr( ctor_key_token(0), std::move(*o.state) )
{}
value_ptr& operator=(value_ptr const& o) {
*state = *o.state;
return *this;
}
value_ptr& operator=(value_ptr && o) {
*state = std::move(*o.state);
return *this;
}
T* get() const { return state.get(); }
T* operator->() const { return get(); }
T& operator*() const { return *state; }
template<class U,
std::enable_if_t<std::is_convertible<T const&, U>{}, int> =0
>
operator value_ptr<U>() const& {
return {*state};
}
template<class U,
std::enable_if_t<std::is_convertible<T&&, U>{}, int> =0
>
operator value_ptr<U>() && {
return {std::move(*state)};
}
private:
template<class...Args>
value_ptr( ctor_key_token, Args&&... args):
state( std::make_unique<T>(std::forward<Args>(args)...) )
{}
std::unique_ptr<T> state;
};
that is a rough sketch of a non-nullable heap-allocated value semantics object.
Note that when you move-from it, it doesn't free the old memory. The only time it doesn't own a T on the heap is during construction (which can only abort via a throw) and during destruction (as state is destroyed).
Fancier versions can have custrom destroyers, cloners and movers, permitting polymorphic value semantic types or non-copyable types to be stored.
Using types that are almost-never-null or rarely-null as never-null leads to bugs. So don't do it.
Live example.
It's not possible, in C++'s type system, to write a non-nullable unique_ptr. unique_ptr being nullable is not just convention. This is the point that is badly being missed in many of the comments. What would the move constructor look like? This point has been covered before: https://youtu.be/zgOF4NrQllo?t=38m45s. Since a non-nullable unique_ptr type is not possible, you may as well use unique_ptr pointer in either case.
If you want, you could create a pointer type that is just like unique_ptr, but doesn't have a public default constructor. It would still enter the null state every time it was moved from. This doesn't give you much in the way of guarantees, but it gives you a little, and it serves as documentation. I don't think this type is worth enough to justify its existence.
I suggest simply making it a convention in the codebase that a std::unique_ptr always points to something unless it's a class member being initialized inside a constructor or has just been dereferenced and is about to go out of scope (and only in these cases may it contain null)

Implementing unique_ptr: Deleting non-allocated objects

My goal here is to implement a simple version of unique_ptr which offers only a constructor, destructor, ->, *, and release().
However, I don't know what to do in the case where a unique_ptr is initialized using a non-allocated pointer.
eg
int i = 0;
unique_ptr<int> p{&i};
If the unique_ptr simply calls delete on it owned pointer, this will produced undefined (and undesirable) behavior, at least as far as I know. What can I do to prevent this?
EDIT: My attempt at the problem is as follows...
template<typename T>
class Uptr
{
public:
Uptr<T>(T* pt) : mp_owned{pt} {}
~Uptr<T>() {delete mp_owned;}
Uptr<T>(const Uptr<T>&) = delete;
Uptr<T>& operator=(const Uptr<T>&) = delete;
T& operator*() const {return *mp_owned;}
T* operator->() const {return mp_owned;}
T* release() {return mp_owned;}
private:
T* mp_owned;
};
You cannot check programmatically how a pointer value was obtained. In your situation (which is highly representative of large parts of real programming!), the solution is to document your interface to require that the pointer value be deletable. You place a precondition on your users, which requires that your users read the documentation and follow it, and you do not and cannot provide in-language methods for validating those preconditions. You pass the burden on to your users.
Such precondition burdens always form a kind of "technical debt", and you want to avoid it as much as you can (but perhaps not at the expense of runtime cost). For example, in the standard library we would strongly discourage the use of the ownership-taking constructor of unique_ptr and instead as the user to use make_unique, which has no preconditions and results in a valid unique_ptr value. That design is exemplary for how you would manage technical debt in the real world.
Unfortunately, there is nothing you can do about this: the ownership of the object must be transferred to unique_ptr<T>, which is not possible if you use addresses of objects in global, static, or automatic areas.
The implementation from the standard library, i.e. std::unique_ptr<T,Deleter>, takes a deleter parameter, which you can use to not delete anything. However, this use is highly questionable, because in this situation you do not need unique_ptr at all.

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++ pointer container with reference counting

I need a collection in which i can store heap-allocated objects having virtual functions.
I known about boost::shared_ptr, std::unique_ptr (C++11) and boost::ptr_(vector|list|map), but they doesn't solve duplicate pointer problem.
Just to describe a problem - i have a function which accepts heap-allocated pointer and stores it for future use:
void SomeClass::add(T* ptr)
{
_list.push_back(ptr);
}
But if i call add twice with same parameter ptr - _list will contain two pointers to same object and when _list is destructed multiple deletion of same object will occur.
If _list will count pointer which he stores and uses them at deletion time then this problem will be solved and objects will not be deleted multiple times.
So the question is:
Does somebody knows some library with collections (vector,list,map in essence) of pointer with auto-delete on destruction and support of reference counting?
Or maybe i can solve this problem using some other technique?
Update:
I need support of duplicate pointers. So i can't use std::set.
As Kerrek SB and Grizzly mentioned - it is a bad idea to use raw pointers in general and suggests to use std::make_shared and forget about instantiation via new. But this is responsibility of client-side code - not the class which i designs. Even if i change add signature (and _list container of course) to
void SomeClass::add(std::shared_ptr<T> ptr)
{
_list.push_back(ptr);
}
then somebody (who doesn't know about std::make_shared) still can write this:
SomeClass instance;
T* ptr = new T();
instance.add(ptr);
instance.add(ptr);
So this is not a full solution which i wait, but useful if you write code alone.
Update 2:
As an alternative solution i found a clonning (using generated copy constructor). I mean that i can change my add function like this:
template <typename R>
void SomeClass::add(const R& ref)
{
_list.push_back(new R(ref));
}
this will allow virtual method (R - class which extends some base class (interface)) calls and disallow duplicate pointers. But this solution has an overhead for clone.
Yes: std::list<std::shared_ptr<T>>.
The shared pointer is avaiable from <memory>, or on older platforms from <tr1/memory>, or from Boost's <boost/shared_ptr.hpp>. You won't need to delete anything manually, as the shared pointer takes care of this itself. You will however need to keep all your heap pointers inside a shared pointer right from the start:
std::shared_ptr<T> p(new T); // legacy
auto p = std::make_shared<T>(); // better
If you another shared pointer to the same object, make a copy of the shared pointer (rather than construct a new shared pointer from the underlying raw pointer): auto q = p;
The moral here is: If you're using naked pointers, something is wrong.
Realize that smart pointers are compared by comparing the underlying container. So you can just use a std::set of whatever smartpointer you prefer. Personally I use std::unique_ptr over shared_ptr, whenever I can get away with it, since it makes the ownership much clearer (whoever holds the unique_ptris the owner) and has much lower overhead too. I have found that this is enough for almost all my code. The code would look something like the following:
std::set<std::unique_ptr<T> > _list;
void SomeClass::add(T* ptr)
{
std::unique_ptr<T> p(ptr);
auto iter = _list.find(p);
if(iter == _list.end())
_list.insert(std::move(p));
else
p.release();
}
I'm not sure right now if that is overkill (have to check if insert is guaranteed not to do anything, if the insertion fails), but it should work. Doing this with shared_ptr<T> would look similar, although be a bit more complex, due to the lack of a relase member. In that case I would probably first construct a shared_ptr<T> with a do nothing deleter too pass to the call to find and then another shared_ptr<T> which is actually inserted.
Of course personally I would avoid doing this and always pass around smart pointers when the ownership of a pointer changes hands. Therefore I would rewrite SomeClass::add as void SomeClass::add(std::unique_ptr<T> ptr) or void SomeClass::add(std::shared_ptr<T> ptr) which would pretty much solve the problem of having multiple instances anyways (as long as the pointer is always wrapped).

Pointer container class which can't be copied by value

I need a smart pointer for my project which can be send to several methods as parameter. I have checked auto_ptr and shared_ptr from boost. But IMO, that is not suitable for my requirements. Following are my findings
auto_ptr : When passed to another method, ownership will be transferred and underlying pointer will get deleted when that method's scope ends. We can workaround this by passing auto_ptr by reference, but there is no compile time mechanism to ensure it is always passed by reference. If by mistake, user forgot to pass a reference, it will make problems.
boost::shared_ptr : This looks promising and works correctly for my need. But I feel this is overkill for my project as it is a very small one.
So I decided to write a trivial templated pointer container class which can't be copied by value and take care about deleting the underlying pointer. Here it is
template <typename T>
class simple_ptr{
public:
simple_ptr(T* t){
pointer = t;
}
~simple_ptr(){
delete pointer;
}
T* operator->(){
return pointer;
}
private:
T* pointer;
simple_ptr(const simple_ptr<T>& t);
};
Is this implementation correct? I have made copy constructor as private, so that compiler will alert when someone tries to pass it by value.
If by chance the pointer is deleted, delete operation on the destructor will throw assertion error. How can I workaround this?
I am pretty new to C++ and your suggestion are much appreciated.
Thanks
Please use boost::scoped_ptr<> as suggested by Martin York, because it:
Does exactly what you want (it's a noncopyable pointer)
Has no overhead above that of a standard C pointer
Has been carefully crafted by super-intelligent C++ wizards to make sure it behaves as expected.
While I can't see any problems with your implementation (after applying the changes suggested by ChrisW), C++ has many dark corners and I would not be surprised if there is some obscure corner case which you, I and the others here have failed to spot.
What you have done is boost::scoped_ptr
Please also read comment by j_random_hacker.
Is this implementation correct? I have made copy constructor as private ...
You could do the same for the assignment operator:
simple_ptr& operator=(const simple_ptr<T>& t);
A const version of the dereference operator might be useful too, and, smart pointers usually define the other kind of dereference operator as well:
const T* operator->() const { return pointer; }
const T& operator*() const { return *pointer; }
T& operator*() { return *pointer; }
If by chance the pointer is deleted, delete operation on the destructor will throw assertion error. How can I workaround this?
Do you mean, if I do this:
//create instance
Car* car = new Car;
//assign to smart ptr
simple_ptr<Car> ptr(car);
//explicit delete
delete car;
//... assertion when ptr is destroyed ...
A way (I don't know if it's a good way) to prevent that is to declare the constructor, and/or the destructor, and/or the delete operator of the T class as private, and say that simple_ptr is a friend of the T class (so that only the simple_ptr class can create and/or destroy and/or delete instances of T).
Marking the new operator as private in T class seems to be impossible as I have to modify all the classes which will be used with simple_ptr
Yes that's true: to do my suggestion immediately above, you would need to modify the class definitions.
If your question is "how can I make double deletes impossible, without modifying class definitions?" then I think the answers are:
You can't: it's up the application code (which uses these classes) to be careful
You can: by providing your own heap manager i.e. your own implementation of global operator new and global operator delete and, in your smart_ptr code, interrogate your heap manager to see whether this incarnation of this pointer is still allocated, before you delete it
To answer your first question, the best assurance you can get that this is correct is to implement a test harness around it to do some simple task, and make sure you get the behavior you expect. For me, that is far better comfort the code is right than the opinion of some random person reading it.
As for your second question, you work around delete throwing an assertion error by setting pointer to some marker value after you delete it the first time. Something like:
if (pointer) {
delete pointer;
pointer = NULL;
} else {
error("Attempted to free already freed pointer.");
}
The problem you're going to run into here is that your overloaded -> operator returns the value of the pointer, which means whoever you return this to can also call delete, causing the check I propose above not to work. For example:
simple_ptr<int> myPtr = someIntPointer;
...
delete myPtr.operator->(); /* poof goes your pointered memory region */
I might recommend that you not rely on the operator-> overloading, and just require that those using this class call a method that dereferences the pointer internally before passing that value back to the user.
Hope this helps.
You should user a boost::scoped_ptr<> as has been mentioned already.
In general though, if you need to make a class non-copyable, you should inherit from boost::noncopyable, i.e.
#include <boost/utility.hpp>
class myclass : boost::noncopyable
{
...
};
This does all the work of making it non-copyable and is nicely self-documenting.
You've got two choices:
boost::scoped_ptr already detailed by j_random_hacker, because it's non-copyable (doesn't share ownership like shared_ptr) and non-movable (doesn't transfer ownership like auto_ptr. auto_ptr has a copy constructor, but that one does not copy. It moves the original pointer to *this). boost::scoped_ptr is exactly what you need.
const auto_ptr doesn't allow transfer of ownership. And take your parameter by reference to const (auto_ptr<T> const&). If the writer of a function accepts by value instead, it still won't work if you try passing a const auto_ptr, because its copy constructor needs a non-const auto_ptr.
Until C++1x, boost::scoped_ptr is the best choice for your needs, or a const auto_ptr if you have to use official standard stuff (read this). In C++1x, you can use std::unique_ptr as a better alternative to auto_ptr, because you have to explicitly state when you want to transfer ownership. Trying to copy it will result in a compile time error. unique_ptr is detailed a little in this answer.
I've seen sometimes usage of simple DISABLE_COPY macros:
#define DISABLE_COPY(Class) \
Class(const Class &); \
Class &operator=(const Class &);
So it's a common practice to define copy constructor and assignment operator as private for your task.