transferring object ownership on std::allocator rebind - c++

I have a Visual Studio 2008 C++ application where I am implementing a replacement for the standard allocator used in containers like std::vector. But, I've run in to an issue. My implementation relies on the allocator owning a handle to a resource. In the case where the rebind feature is used, I would need to transfer ownership of the handle to the new allocator. Something like this:
template< class T >
class MyAllocator
{
public:
template< class U >
explicit MyAllocator( const MyAllocator< U >& other ) throw()
: h_( other.Detach() ) // can't do this to a `const`
{
};
// ...
private:
HANDLE Detach()
{
HANDLE h = h_;
h_ = NULL;
return h;
};
HANDLE h_;
}; // class MyAllocator
Unfortunately, I can't relieve the old allocator of the handle ownership because it is const. If I remove const from the rebind constructor, then the containers won't accept it.
error C2558: class 'MyAllocator<T>' : no copy constructor available or copy constructor is declared 'explicit'
Is there a good way around this issue?

Without really knowing much about allocators (never needed them): Your copy ctor takes a const ref, thus promising to not to change the other object, but you attempt to change it anyway. Although there's cases where classes were designed that way (std::auto_ptr), this does seem fishy.
Syntactically, you could always declare h_ mutable, and make Detach() a const member function, but I'd seriously question the semantics of this setup, before hacking my way through the syntactic jungle using a broadsword.

What happens if you declare h_ as mutable?

You can solve this with an extra level of indirection but it's not an ideal solution. Basically, your allocator would have a pointer to a handle which would be allocated/deallocated in the constructor/destructor. The handle that it points to would be non-const throughout, so you can "move" the handle from one allocator to another. This does add some overhead to the allocator though.
I don't know your exact case but it seems that a stateful allocator that's non-trivially copyable should be carefully considered for all its implications. Is there an alternate way you can simplify its design so it doesn't have a move-only handle?

You can't transfer the ownership, because the allocator may be copied and rebound multiple times even in a single container and the resulting instances used simultaneously.
You'll have to share the resource instead. Create an indirection for the resource with reference-count. Something like:
class SharedHandle {
HANDLE h_;
int count;
SharedHandle(HANDLE h) : h_(h), count(1) {}
~SharedHandle() { CloseHandle(h_); } // or whatever to release the resource.
SharedHandle *Ref() { ++count; return this; }
void Unref() { if(!--count) delete this; }
}
and than:
explicit MyAllocator( const MyAllocator< U >& other ) throw()
: h_( other.h_->Ref() )
In addition to containers that naturally need to allocate heterogenous blocks like hash_map/unordered_map, Microsoft implementation of containers is known to allocate various strange things. When I traced allocations in one Windows application, there were many allocations of strange sizes comming from somewhere inside STL.

Related

Is it sensible to use shared_ptr instead of unique_ptr as class member just to avoid implicit copy constructor deletion?

I would like to preserve the default copy-constructor of a large-ish (but say not particularly complex*) class, but ideally would like to replace some raw pointer member with a smart-pointer alternative.
unique_ptr seems to be the default for this, but it implicitly deletes the copy constructor for my class.
shared_ptr instead would allow me to preserve the class' copy constructor. Could that likely be a good reason to simply stick to shared_ptr, even if I do not genuinely want to 'share' the resource; I really only want to preserve the readily available copy constructor (annoying to write a manual copy constructor for the entire class, just to replace a pointer with a unique_ptr), just as I had it when I still used raw pointer.
Searching for when to use shared_ptr vs. unique_ptr, I never see the simple preservation of the copy-constructor indicated as a possible key reason to use shared_ptr (possible exception https://stackoverflow.com/a/16030118/3673329 but not giving any detail), but I also do not directly see any reason why this could not be a valid choice.
I reckon shared_ptr may be a bit more resource intensive, but assume my case where this is no real problem.
*In particular, the default/shallow copying of the class was fine for my purposes as long as I used raw pointer members instead of smart ones.
If the only reason to use std::shared_ptr is to retain default copy constructibility of your class, you prioritize ease of use over the intended semantics of your class with respect to resource handling. In my opinion, you have to decide up front whether the class shall share its resources or exclusively own it. If you are unsure whether the class should share its resources with copied instances or not, something else in the design might at least be suspicious.
There might be an exception to this guideline, and that is std::shared_ptr<const YourType>. In the case of read only access, it might be acceptable to use such a technique to allow for default copy construction (although in a different context, here is where Sean Parent says that std::shared_ptr<const T> is acceptable to obtain value semantics).
Note one further implication: if you share a std::shared_ptr instance, you are not only sharing state and functionality of the pointee, you also share lifetime control. If the latter is not what you intend, just share a reference (preferable) or a raw pointer to the pointee, with access e.g. via a getter-like member function. If the consuming parts of your class can't know whether the pointee is still alive or has already been destroyed, a std::weak_ptr could be an option.
There is still a great deal of advantage in using a unique_ptr and providing the missing copy operations manually.
You get the correctness guarantees plus an easy customisation point for inner object cloning.
example:
#include <memory>
struct LargeImplObject
{
int x[1000];
};
struct CopyableHandle
{
using impl_class = LargeImplObject;
using implementation_type = std::unique_ptr<impl_class>;
CopyableHandle()
: impl_(construct())
{}
CopyableHandle(CopyableHandle&&) noexcept = default;
CopyableHandle& operator=(CopyableHandle&&) noexcept = default;
CopyableHandle(CopyableHandle const& other)
: impl_(other.clone())
{}
CopyableHandle& operator=(CopyableHandle const& other)
{
impl_ = other.clone();
return *this;
}
// note: no destructor
private:
// customisation points
static auto construct() -> implementation_type
{
return std::make_unique<impl_class>();
}
auto clone() const -> implementation_type
{
return std::make_unique<impl_class>(*impl_);
}
implementation_type impl_;
};
int main()
{
auto a = CopyableHandle();
auto b = a;
auto c = std::move(a);
a = std::move(c);
}

Enforce no bald pointers in C++

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.

SMART vector for RAW pointers in C++11?

I'm using an old open-source library, with the following (simplified) API of interest:
// some class that holds a raw pointer to memory on the heap
// DOES NOT delete it in its destructor
// DOES NOT do a "deep" copy when copied/assigned (i.e., after copying both objects
// will point to the same address)
class Point;
// function used to construct a point and allocate its data on the heap
Point AllocPoint();
// function used to release the memory of the point's data
void DeallocPoint(Point& p);
// Receives a pointer/c-array of Points, along with the number of points
// Doesn't own the memory
void Foo(Point* points, int npts);
What's the best (safest/most readable/most elegant) way of using this API in C++11. I can't simply use vector<unique_ptr<Point, PointDeleter>> (where PointDeleter is a simple custom deleter I can implement), because then I will not be able to use the function Foo (which expects Point* and not unique_ptr<Point>*).
Thanks
If you really want to make it look nice, you're probably going to have to write a set of really comprehensive wrappers which completely hide the library's API - effectively, wrap the entire library with one that behaves in a modern C++ way on the outside and hides all the mess inside.
Not a pleasant task, but if you can get the behaviour of that library right then it should make your life a lot easier in the long term. Might not be worth it if you're not going to use this external library very extensively though.
I would wrap this non-RAII C-like API in RAII building blocks, and then use them in C++11 code.
For example: you can define a RaiiPoint class that wraps the (non-RAII) Point class, and in its constructor calls AllocPoint(), in the destructor DeallocPoint(). Then you can define proper copy constructor and copy operator=, or just implement move semantics (with move constructor and move operator=), or make the wrapper class both copyable and movable, basing on your requirements.
Then you can simply use a std::vector<RaiiPoint> with your RAII-based wrapper class.
(This is a general approach that you can use when you want to use C libraries in modern C++ code: you can wrap the "raw" C library handles and objects in safe RAII boundaries, and use these robust safe wrapper classes in your modern C++ code.)
You can use std::vector<Point>, calling Foo( &v[0],
v.size() ). But managing the memory here could be tricky,
since Point apparently doesn't provide any clean copy and
assignment; a custom deleter in the allocator will be called for
each element, even if it is copied.
If the vector should actually own the points, then you can wrap
it in a more complex class, which calls AllocPoint for each
insertion (and inserts the results), and DeallocPoint for each
removal (and for everything remaining in the vector on
destruction). This class should not allow write access to the
Point (non-const operator[], non-const iterators, etc.),
however, since this would allow changing any pointers in
Point, and loosing what is needed for DeallocPoint to work
correctly. Presumably, there other functions for manipulating
Point; you'll have to arrange for these to be available
through the wrapper interface.
"You" could write a simple wrapper to free the memory:
struct PointVectorWrapper {
vector<Point> points;
~PointVectorWrapper() {
for (Point& p : points) {
DeallocPoint(p);
}
}
PointVectorWrapper& operator=(const PointVectorWrapper&) = delete;
PointVectorWrapper(const PointVectorWrapper&) = delete;
};
// Now the usage is simple and safe:
PointVectorWrapper points;
// ... populate points ...
Foo(points.data(), points.size())
But this seems a little "adhoc". What's a more standard/reusable solution?
You could use a standard vector with a custom allocator, that invoke AllocPoint on construct method and DeallocPoint() on destruct method.
template<typename T>
class CustomAllocator : public std::allocator<T>
{
//Rebind and constructors
};
template<>
class CustomAllocator<Point> : public std::allocator<Point>
{
//Rebind and constructors
//For c++11
void construct( pointer p )
{
new (p) Point();
*p = AllocPoint();
}
void construct( pointer p, const_reference val )
{
construct(p);
//copy member from val to point if neccessary
};
void destroy( pointer p )
{
DeallocPoint(*p);
p->~Point();
}
};
typedef std::vector<Point, CustomAllocator<Point> > PointVector;

Efficient ways to initialize class members; both heap and stack allocated

Assume we have the following:
//! SomeClass.hpp
class
{
public:
SomeClass( void );
~SomeClass( void )
{
delete mFoo;
delete mBar;
}
...
private:
Foo* mFoo;
Bar* mBar;
StackObj mStackFoo;
};
//! SomeClass.cpp
SomeClass::SomeClass( void )
{
mFoo = new Foo;
mBar = new Bar;
mStackFoo = StackObj( ... );
}
Now, when we initialize the pointers, my understanding is that the constructor will create unnecessary copies of SomeClass' members, thus allocating and then deallocating memory simply for the sake of allocating memory.
It's common to use initializer lists, coupled with a separate initialization function (for heap allocated memory) as a method to avoid this. Say SomeClass has a private member function defined as void initHeapMem( void ). Then we can do,
SomeClass::SomeClass( void )
: mFoo( NULL ),
mBar( NULL ),
mStackFoo( ... )
{
initHeapMem();
}
void SomeClass::initHeapMem( void )
{
mFoo = new Foo;
mBar = new Bar;
}
Naturally, this somewhat fixes the problem. The issue here I believe is that there's still the overhead of another function call being performed.
The reason why we can't use initialization lists for raw pointers is because they're not thread safe. If something goes wrong, and the program throws an exception, there will still be a memory leak. Note: this is according to what I've read, my apologies if this is wrong.
So, with boost/C++11, we can use smart pointers from an #include <tr1/memory> directive in the header file ( assuming we're using STL ).
If we were to use, say, std::unique_ptr< T >, then we'd have Bar* mBar and Foo* mFoo replaced with:
std::unique_ptr< Foo > mFoo;
std::unique_ptr< Bar > mBar;
Which would then allow us to do,
SomeClass::SomeClass( void )
mFoo( new Foo ),
mBar( new Bar ),
mStackFoo( ... )
{
}
Since the smart pointer effectively wraps the memory allocation in its own constructor.
While this is a nice solution, I personally am not one to use smart pointers for every heap object I create, and I know there are others in the C++ community who feel the same way.
tl;dr
With all of that out of the way, what I'm really wondering is if there are any more efficient alternatives to initializing class members within an object (especially with the advent of C++11), apart from the ones I listed above.
unique_ptr is the right solution here. It has several advantages:
It explicitly documents ownership. One of the issues with raw pointers is that they don’t indicate anything about who owns them. With unique_ptr you have a single owner, and must explicitly move ownership should you want to transfer it.
It has essentially no overhead; the only thing unique_ptr does is invoke the deleter, which you were going to do anyway. Now you have the performance benefits of deterministic memory behaviour without the effort of manual memory management.
It makes thread- and exception-safety much easier to attain, thanks to RAII. That means less fretting about instruction order, and less explicit cleanup code. You get the benefits of exceptions without all of the problems that caused them to be avoided in so much C++03 code.
shared_ptr is in my experience needed much less often than unique_ptr. Shared ownership is useful mainly when you have an immutable resource such as a texture or audio file, where loading and copying are both expensive, but which you want to unload when it’s not in use. shared_ptr also imposes the overhead of added safety (thread-safety in particular) and reference counting.
The disadvantage, of course, is that smart pointers impose a syntactic overhead. They are not as “native” as raw pointers. For that, you have typedef, auto, decltype, and rolling your own convenience functions such as make_unique.
Why can't you do this?
SomeClass::SomeClass( void ) :
mFoo(new Foo)
, mBar(new Bar)
{
}
They are raw pointers and no unnecessary copies are created.
I should also point out that the reason you use initializer lists is so that the object is in a valid state (that is, all members have valid values) when the constructor body is executed.
SomeClass::SomeClass( void )
{
//before this point, mFoo and mBar's values are unpredictable
mFoo = new Foo;
mBar = new Bar;
}
Regarding exceptions, the destructor of SomeClass will not be called ONLY if the exception is thrown inside the constructor itself.
Finally, regarding being thread safe or not, it depends on whether each thread has its own copy of SomeClass or not and whether SomeClass contains static members that are being written to.

template specialization of a auto_ptr<T>

Maybe I'm overcomplicating things, but then again, I do sort of like clean interfaces. Let's say I want a specialization of auto_ptr for an fstream - I want a default fstream for the generic case, but allow a replacement pointer?
template <>
class auto_ptr<fstream> {
static fstream myfStream;
fstream* ptr;
public:
auto_ptr() {
// set ptr to &myfStream;
}
reset(fstream* newPtr) {
// free old ptr if not the static one.
ptr = newPtr
};
}
Would you consider something different or more elegant? And how would you keep something like the above from propagating outside this particular compilation unit?
[The actual template is a boost::scoped_ptr.]
EDIT:
It's a contrived example. Ignore the fstream - it's about providing a default instance of object for an auto_ptr. I may not want to provide a specialized instance, but would like to keep the auto_ptr semantics for this static default object.
class UserClass {
public:
auto_ptr<fstream> ptr;
UserClass() { }
}
I may not provide an dynamic object at construction time - I still want it to have a meaningful default. Since I'm not looking at ownership-transfer semantics, it really shouldn't matter that my pointer class is pointing to a statically allocated object, no?
This wouldn't end up good. The biggest problem is that std::auto_ptr deletes the underlying object in its destructor. This means your default parameter can't be static. The only choice you can make is to do a lot of hacks there and IMHO the price you'll pay while maintaining all that crappy code isn't worth the small advantage you'd have.
That looks reasonable to me, could be confusing if it's use is widespread in a codebase and not documented though.
I notice you are being carful, but I'm going to stress it anyway: make sure you don't double-free your static object!
You might get something that compiles and works, but I wouldn't do that if I were you.
Boost defines certain functionality for the construction of an auto_ptr. If you redefine that somehow, you have violated their specification.
Invent a name for your new functionality, make it a factory function, and don't worry about specializing someone else's template.
EDIT: deriving from auto_ptr is another option, if you're really set on changing initialization semantics:
tempate < class T, T *d >
struct defaulted_auto_ptr
: public auto_ptr< T > {
defaulted_auto_ptr( T *p = d ) throw() : auto_ptr<T>( p ) {} // set default
defaulted_auto_ptr( auto_ptr<T> &r ) throw()
: auto_ptr<T>( r ) {} // allow conversion
template< class O > defaulted_auto_ptr( auto_ptr<O> &r ) throw()
: auto_ptr<T>( r ) {}
};
fstream default_file;
typedef defaulted_auto_ptr< fstream, &default_file > file_ptr;
auto_ptr< fstream > baseptr = file_ptr(); // can assign to auto_ptr, but unsafe
I'm a little doubtful of the cost-benefit tradeoff of this, but it's better than entirely reimplementing auto_ptr.
You still have to figure out what to do if a defaulted object is destroyed. default_file above will be deleted, potentially many times.