First, I know about unique_ptr and share_ptr, but I'm not using C++11 and thus I can't use them.
Every possible research from google returns a solution using those two smart pointers. I would like one without.
I need to pass ownership of a pointer to another class through the constructor.
PointerToPass* myPointer = new PointerToPass();
MyClass* myClass = new MyClass(myPointer);
So I could use raw pointers but I read everywhere that I should avoid it.
Using a reference is not an option.
I could use a smart pointer from Qt to show that I pass ownership like so:
QScopedPointer<PointerToPass> myPointer(new PointerToPass());
MyClass* myClass = new MyClass(myPointer.take());
This option clearly shows that the pointer is passed and that the ownership is given to myClass even if it's still using raw pointers.
Is there a better way to convey this idea?
It would be even better if it could be seen in the MyClass constructor signature.
What about clear indication pointer is not to be used outside?
class myClass {
public: myClass(PointerToPass*& p): _p(p) {
p = nullptr;
}
public: ~myClass() {
delete _p;
}
private: PointerToPass* _p;
};
PointerToPass* myPointer = new PointerToPass();
MyClass* myClass = new MyClass(myPointer);
std::cout << myPointer << "\n";
The C++ Core Guidelines has some advice about this and suggest you use owner from the Guideline Support Library (GSL) to annotate raw pointers.
template <class T>
using owner = T;
This is just a typedef of owner<T> to T. It serves only as annotation and would work for your constructor argument. If this syntax wasn't C++11.
We could use a similar idea instead though.
template<typename T>
struct owner
{
typedef T pointer;
};
MyClass(owner<PointerToPass*>::pointer p)
{
// ...
}
Similar to the technique in the guidelines, this doesn't actually enforce anything. It does annotate the code to make the ownership sematics clearer though.
Related
I have read through many questions on SO on custom deleter for shared_ptr and unique_ptr, and the difference between the two. But, I still haven't found any clear answer to this question:
How can one best go about creating a type that acts as a shared_ptr with a custom deleter, similar to how unique_ptr has the deleter as part of the type definition?
For unique_ptr usage, I use a deleter class, that handles deletion of individual types (limiting it to just two types, for brevity):
struct SDL_Deleter {
void operator()( SDL_Surface* ptr ) { if (ptr) SDL_FreeSurface( ptr );}
void operator()( SDL_RWops* ptr ) { if (ptr) SDL_RWclose( ptr );}
};
using SurfacePtr = std::unique_ptr<SDL_Surface, SDL_Deleter>;
using RWopsPtr = std::unique_ptr<SDL_RWops, SDL_Deleter>;
Which can be used with something like
SurfacePtr surface(IMG_Load("image.png"));
And will call SDL_FreeSurface upon destruction.
This is all fine and well. However, how does one go about achieving the same for shared_ptr? Its type is defined as
template< class T > class shared_ptr;
and the way to provide a custom deleter is through the constructor. It doesn't feel right that the user of the shared_ptr wrapper needs to know which pointer type is wrapped, and how that pointer is supposed to be deleted. What would be the best way to achieve the same kind of usage as with the unique_ptr example of above.
In other words, that I could end up with:
SurfaceShPtr surface(IMG_Load("image.png"));
Instead of of something like
SurfaceShPtr surface(IMG_Load("image.png"),
[=](SDL_Surface* ptr){SDL_FreeSurface(ptr);});
Or, just slightly better
SurfaceShPtr surface(IMG_Load("image.png"),
SDL_Deleter());
Is there a way to do this, without having to create a RAII wrapper class (instead of a typedef), adding even more overhead?
If the answer is "this isn't possible". Why not?
The other answer provided here was that something close to what I asked could be done through function returns of unique_ptr with custom deleter, which can be implicitly converted to a shared_ptr.
The answer given was that a deleter defined as a type trait was not possible for std::shared_ptr. The answer suggested as an alternative, to use a function which returns a unique_ptr, implicitly converted to a shared_ptr.
Since this isn't part of the type, it is possible to make a simple mistake, leading to memory leaks. Which is what I wanted to avoid.
For example:
// Correct usage:
shared_ptr<SDL_Surface> s(createSurface(IMG_Load("image.png")));
// Memory Leak:
shared_ptr<SDL_Surface> s(IMG_Load("image.png"));
The concept I want to express is having the deleter as part of the type (which unique_ptr allows), but with the functionality of a shared_ptr. My suggested solution is deriving from shared_ptr, and providing the deleter type as a template argument. This takes up no additional memory, and works in the same way as for unique_ptr.
template<class T, class D = std::default_delete<T>>
struct shared_ptr_with_deleter : public std::shared_ptr<T>
{
explicit shared_ptr_with_deleter(T* t = nullptr)
: std::shared_ptr<T>(t, D()) {}
// Reset function, as it also needs to properly set the deleter.
void reset(T* t = nullptr) { std::shared_ptr<T>::reset(t, D()); }
};
Together with a deleter class (Thanks Jonathan Wakely. Way cleaner than my macro (now removed)):
struct SDL_Deleter
{
void operator()(SDL_Surface* p) const { if (p) SDL_FreeSurface(p); }
void operator()(SDL_RWops* p) const { if (p) SDL_RWclose(p); }
};
using SurfacePtr = std::unique_ptr<SDL_Surface, SDL_Deleter>;
using SurfaceShPtr = shared_ptr_with_deleter<SDL_Surface, SDL_Deleter>;
using RWopsPtr = std::unique_ptr<SDL_RWops, SDL_Deleter>;
using RWopsShPtr = shared_ptr_with_deleter<SDL_RWops, SDL_Deleter>;
Instances with SurfaceShPtr members are type guaranteed to clean up properly, the same as for SurfacePtr, which is what I wanted.
// Correct Usage (much harder to use incorrectly now):
SurfaceShPtr s(IMG_Load("image.png"));
// Still correct usage
s.reset(IMG_Load("other.png"));
I'll leave this up for a while, for comments, etc, without accepting the answer. Maybe there are even more dangerous caveats I've missed (having a non-virtual destructor not being one, as the parent shared_ptr is given charge of the deletion).
A typedef is a static, compile-time feature.
A deleter passed to a shared_ptr is a dynamic, run-time property. The deleter is "type-erased" and is not part of the shared_ptr interface.
Therefore you can't declare a typedef to represent an alternative deleter, you just pass one to the constructor.
What would be the best way to achieve the same kind of usage as with the unique_ptr example of above.
You could use functions to create the resources and return them in a shared_ptr
shared_ptr<SDL_Surface> create_sdl_surface(const char* s)
{
return shared_ptr<SDL_Surface>(IMG_load(s), SDL_FreeSurface);
}
But I would have those functions return a unique_ptr instead, which can be converted to shared_ptr, as below.
I would get rid of the macro and do something like this:
// type with overloaded functions for freeing each resource type
struct SDL_deleter
{
void operator()(SDL_Surface* p) const { if (p) SDL_FreeSurface(p); }
void operator()(SDL_RWops* p) const { if (p) SDL_RWclose(p); }
// etc.
};
// a unique_ptr using SDL_deleter:
template<typename P>
using SDL_Ptr = std::unique_ptr<P, SDL_deleter>;
// typedefs for the common ptr types:
using SurfacePtr = SDL_ptr<SDL_Surface>;
using RWopsPtr = SDL_ptr<SDL_RWops>;
// etc.
To answer the shared_ptr part of your question, define functions that create resources and return them in a SDL_ptr:
SurfacePtr createSurface(const char* s) { return SurfacePtr(IMG_load(s)); }
RWopsPtr createRWops([...]) { return RWopsPtr([...]); }
// etc.
Then you can easily create a shared_ptr from the result of those functions:
shared_ptr<SDL_Surface> s = createSurface("image.png");
The shared_ptr automatically acquires the right deleter from the unique_ptr.
Generally speaking, in this crazy modern world full of smart pointers, I'm coming round to the fact that bald/bare pointers shouldn't be in method signatures.
I suppose there might be some cases where you need bald pointers for performance reasons but certainly I've always managed with references or references to smart pointers.
My question is this, can anyone suggest an automated way to enforce this? I can't see a way with clang, GCC or vera++
I think it is ok for non-owning raw-pointers to be used in method signatures. It is not ok to use "owning" raw-pointers.
For example this is quite ok:
void bar(const Widget* widget) {
if (widget)
widget->doSomething();
}
void foo() {
Widget w;
bar(&w);
}
If you want the Widget to be nullable you can't use a reference and using a smart pointer would be slower and not express the ownership model. The Widget can be guaranteed to be alive for the whole scope of foo. bar simply wants to "observe" it so a smart pointer is not needed. Another example where a non-owning raw-pointer is appropriate is something like:
class Node {
private:
std::vector<std::unique_ptr<Node>> children_; // Unique ownership of children
Node* parent_;
public:
// ...
};
The Node "owns" its children and when a Node dies its children die with it. Providing encapsulation of Node hasn't been broken, a Node can guarantee its parent is alive (if it has one). So a non-owning raw-pointer is appropriate for a back reference to the parent. Using smart pointers where they are not required makes code harder to reason about, can result in memory leaks and is premature pessimization.
If smart pointers are used throughout instead, all kinds of things can go wrong:
// Bad!
class Node {
private:
std::vector<std::shared_ptr<Node>> children_; // Can't have unique ownership anymore
std::shared_ptr<Node> parent_; // Cyclic reference!
public:
// Allow someone to take ownership of a child from its parent.
std::shared_ptr<Node> getChild(size_t i) { return children_.at(i); }
// ...
};
Some of these problems can be solved by using weak_ptr instead of shared_ptr but they still need to be used with care. A weak_ptr is a pointer that has the option of owning.
The point is to use the appropriate kind of pointer in the appropriate context and to have an ownership model that is as simple as possible.
And no, I don't think there is an automated way of enforcing this, it is part of the design. There are tricks you can use like Cheersandhth.-Alf said to try and enforce a particular class is used in the way you want by restricting access.
I don't know of any automated tool to do this, but such a check wouldn't be too hard to implement in cppcheck, which is open source and AIUI offers an easy way to add new rules.
I don't think it's a good idea to completely stay away from raw (bald, bare) pointers even for function arguments. But it can sometimes be a good idea to make sure that all instances of a certain type are dynamic and owned by smart pointers. This involves two measures:
Ensure (to the degree practical) that the type can only be instantiated dynamically.
Ensure (to the degree practical) that instantiation yields a smart pointer.
The first point is easy: just make the destructor non-public, and voilá, the few remaining ways to instantiate that type non-dynamically are not very natural. Any simple attempt to declare a local or namespace scope variable will fail. As will simple attempts to use that type directly as a data member type:
#include <memory>
template< class Type >
void destroy( Type* p ) { delete p; }
class Dynamic
{
template< class Type > friend void destroy( Type* );
protected:
virtual ~Dynamic() {}
};
//Dynamic x; //! Nope.
struct Blah
{
Dynamic x; //! Nope, sort of.
};
auto main()
-> int
{
//Dynamic x; //! Nope.
new Blah; //!Can't delete, but new is OK with MSVC 12...
}
Visual C++ 12.0 unfortunately accepts the above code as long as the out-commented statements remain out-commented. But it does issue a stern warning about its inability to generate a destructor.
So, Dynamic can only be created dynamically (without using low-level shenanigans, or ignoring that MSVC warning and accepting a memory leak), but how to ensure that every new instance is owned by a smart pointer?
Well you can restrict access to the constructors so that a factory function must be used. Another way to ensure use of the factory function is to define a placement allocation function, operator new, that an ordinary new-expression can't access. Since that's most esoteric and possibly non-trivial, and not of clear-cut value, the below code just restricts access to the constructors:
#include <memory> // std::shared_ptr
#include <utility> // std::forward
// A common "static" lifetime manager class that's easy to be-"friend".
struct Object
{
template< class Type >
static
void destroy( Type* p ) { delete p; }
template< class Type, class... Args>
static
auto create_shared( Args&&... args )
-> std::shared_ptr<Type>
{
return std::shared_ptr<Type>(
new Type( std::forward<Args>( args )... ),
&destroy<Type>
);
}
};
class Smart
{
friend class Object;
protected:
virtual ~Smart() {}
Smart( int ) {}
};
//Smart x; //! Nope.
struct Blah
{
//Smart x; //! Nope, sort of.
};
auto main()
-> int
{
//Smart x; //! Nope.
//new Blah; //!Can't delete.
//new Smart( 42 ); // Can't new.
Object::create_shared<Smart>( 42 ); // OK, std::shared_ptr
}
One problem with this approach is that the standard library's make_shared doesn't support a custom deleter, and shared_ptr doesn't use the common deleter of unique_ptr. One may hope that perhaps this will be rectified in future standard.
Disclaimer: I just wrote this for this answer, it's not been extensively tested. But I did this in old times with C++98, then with a macro for the create-functionality. So the principle is known to be sound.
The problem with this idea is that in the smart pointer world, T* is just a shorthand for optional<T&>. It no longer implies memory management, and as a result it becomes a safe idiom to identify an optional non-owned parameter.
I have an Engine class which contains and owns some Systems. The Engine class has two containers, one map and one vector. Both keep pointers to the Systems.
The addSystem template function should add a pointer of a new System of the wanted type in the map and the addToPipeline should add a pointer of the System passed as a parameter in the vector. I used shared_ptrs for this but I am doing something wrong because I get a double free error if I use the addToPipeline function.
Here is the simplified Engine class:
class Engine
{
public:
template <class T>
T& addSystem();
void addToPipeline(System&);
private:
std::map<std::type_index, std::shared_ptr<System>> m_systems;
std::vector<std::shared_ptr<System>> m_pipeline;
};
void Engine::addToPipeline(System& sys)
{
m_pipeline.push_back(std::shared_ptr<System>(&sys));
}
template <class T>
T& Engine::addSystem()
{
std::shared_ptr<T> system = std::make_shared<T>();
auto inserted = m_systems.emplace(typeid(T),system);
return static_cast<T&>(*(*inserted.first).second);
}
The functions should be used like shown below:
auto& POSITION_SYSTEM = engine.addSystem<PositionSystem>();
engine.addToPipeline(POSITION_SYSTEM);
Any help is appreciated!
In this line:
m_pipeline.push_back(std::shared_ptr<System>(&sys));
You are creating a shared_ptr for an already managed object, since you already wrapped the same object in another smart pointer. So you end up with two reference counts for the same object, thus you get a double free.
This is not how shared_ptr should be used. Instead, you should return a shared_ptr from addSystem and take one as argument for addToPipeline:
void Engine::addToPipeline(std::shared_ptr<System> sys)
{
m_pipeline.push_back(sys);
}
template <class T>
std::shared_ptr<T> Engine::addSystem()
{
std::shared_ptr<T> system = std::make_shared<T>();
m_systems.emplace(typeid(T),system);
return system; // No need to use the return value of emplace
}
The idea with shared_ptrs is that instead of using bare pointers or references, you always pass a shared_ptr (unless ownership doesn't matter - then you can also pass a reference). You have to do it this way because the reference counter is managed by the smart pointers.
Edit: As rozina pointed out: Of course you can still pass references to the managed object, as long as nobody tries to delete the corresponding address. This might actually be preferable if other code is interested in using a certain object, but not concerned about ownership. For example, you might want to have a public interface which allows obtaining a reference to some object that's managed by a smart pointer internally. For example:
class Foo {
public:
Bar& getBar() {
return *m_bar;
}
private:
std::shared_ptr<Bar> m_bar;
};
This is perfectly fine as long as nobody does delete &aFoo.getBar() - which happens if you create a new shared_ptr with that reference, as you did in your original code.
I have template
template <class T>
class A
{
T* t_;
A(){t_ = new T();}
void SetItem(T& t)
{
t_ = t;
}
};
There are 2 cases with this template class
1. A<T> a;
2. A<T*> b;
If I invoke two times SetItem i.e.
a.SetItem(T());
a.SetItem(T());
memory will be cleaned properly?
same if I invoke like this:
b.SetItem(new T());
b.SetItem(new T());
I know that memory will not be cleaned.
Questions:
How to make constrain on template that it takes only T or T* ?
If I use template A<T*> how to prevent leaks. Should I modify class or take care of it outside?
Is there any way to make this work whenever I use A<T> or A<T*> ?
I think that use of smart pointers or auto pointers is an option. But I don't know for sure.
The quick answer is, it's up to the person using the class A to clear up heap allocated memory. If you use a std::list, and store pointers in it, then you (not the list) are responsible for calling delete on them. Don't try to make your templated container detect pointers and delete them.
I'd imagine if you use class A with a pointer template param then at some point you would call delete on the return from GetItem() (which I assume the class would provide).
(Also, SetItem should take a const T&.)
To avoid leaks, you should have destructor which will delete T when the object A is destroyed.
To enable your template to only take pointers you should use type traits. I'm not quite familiar enough with it to give you an example.
template <class T>
class A
{
T* t_;
//Set t_ to nullptr, as you are able to pass new T() to SetItem
A() : t_(nullptr) {}
~A() { delete t_; } // When A is destroyed, t_ will be deleted.
void SetItem(const T& t)
{
t_ = t;
}
};
A is a meaningless class here. The solutions to not make it leak are:
Use a smart pointer. If your object is going to be shared and you don't know the lifetimes, you can use shared_ptr. If it isn't and your A class owns the object, use unique_ptr.
Don't use a pointer at all but use an instance of T within your A. This puts restrictions on the type your class A may hold, but the users of your class can make it hold unique_ptr or shared_ptr by putting that in as the parameterized type. An example is vector which takes objects of type T but users can make their vectors take shared_ptr or unique_ptr.
You must specify if your class takes ownership if the user passes in a pointer. If so your class is really a smart pointer itself.
Which one to use is rather difficult to ascertain in your example as A has no purpose in its existing form.
I have a list of smart pointers. I want some of these smart pointers to act as regular pointers, meaning they are simply a reference to an instance and are not involved in its deallocation. They might for example point to instances allocated on the stack. The other smart pointers in the list should act as regular boost::shared_ptr.
Here is how the class might look:
template<class T> smart_ptr {
private:
T *p;
boost::shared_ptr<T> sp;
public:
smart_ptr(T *p): p(p), shared(0) { } // p will not be deleted
smart_ptr(boost::shared_ptr<T> &sp): p(sp.get()), sp(sp) { }
T *get() const { return p; }
}
If there is a boost class that does this, I would prefer to use it instead of writing a class myself. It appears there are none, or am I mistaken?
One constructor for shared_ptr takes the destructor method, and you can pass in an empty functor.
Using Custom Deallocator in boost::shared_ptr
(You want just an empty function.)
I've got this little class in my toolbox for this:
struct nodelete {
template <typename T>
void operator()( T * ) {}
};
Usage:
int main() {
SomeClass sc;
boost::shared_ptr<SomeClass> p( &sc, nodelete() );
// ...
}
This sounds like a boost::weak_ptr:
http://www.boost.org/doc/libs/1_35_0/libs/smart_ptr/weak_ptr.htm
But you can only create a weak_ptr from a shared_ptr, so as for your stack-allocated objects, I'm not sure how that would work.
This smells of bad design.
I can't think of a reasonable situation where you wouldn't want to delete the pointer. Here are the (unreasonable IMO) situations:
1) static duration objects. Instead, consider using a singleton mixin (use CRTP to mixin the singleton that has an instance() method that returns a copy of a local static shared_ptr<>; local statics are thread unsafe so you'll also need an appropriate static mutex if this could be called by multiple threads). The benefit of using a proper singleton is that your singleton will be destructed at exit after other objects that continue to hold shared_ptr<>'s to it.
2) objects created on the stack. Just don't do this. Instead create the object on the heap protected by a shared_ptr<>. If you need to create shared_ptr<>'s to the object in different parts of the code (i.e. you can't take copies from an original shared_ptr<>) then inherit from boost::enable_shared_from_this<> and get shared_ptr<>'s from shared_from_this().
Is there some other reason you want a shared_ptr<> that doesn't ever delete anything?