There are classes that I write (often as part of boost::asio) whose objects depend on being wrapped in a shared_ptr because they use shared_from_this(). Is there a way to prevent an object from being compiled if it's not instantiated in a shared_ptr?
So, what I'm looking for:
std::shared_ptr<MyClass> a = std::make_shared<MyClass>(); // should compile fine
std::unique_ptr<MyClass> a = std::make_unique<MyClass>(); // compile error
MyClass a; // compile error
Make its constructor private and give it a static factory member function that creates a shared_ptr. Don't forget to document your design decision in a comment!
// Thing that foos the bar
struct Foo : std::enable_shared_from_this<Foo>
{
// Returns a shared_ptr referring to a new instance of Foo
static std::shared_ptr<Foo> CreateShared()
{
return std::shared_ptr<Foo>(new Foo);
}
private:
// To avoid bugs due to the shared_from_this base,
// we restrict Foo creation to being via CreateShared().
Foo() = default;
};
(I can't imagine that std::make_shared would work due to the private ctor, but you can try it.)
I've got to say, though, this doesn't sound like the sort of thing a class should be taking responsibility for. It's kind of programming backwards.
To steal Eljay's words:
In general, it is best (if possible) that objects are not self-aware if they are contained in a shared_ptr, or on the heap, or on the stack, or by pointer, or in a vector, or as a data member, or as a global. As soon as they are self-aware of how they are life-cycle managed, they become a lot more constrained. Unnecessarily so. shared_from_this is (arguably) an anti-pattern. But... sometimes it may be a necessary anti-pattern.
I would prefer avoiding enable_shared_from_this and letting people use your Foo however they see fit, such as through a nice lean unique_ptr.
Related
I am trying to hold a unique pointer to both a vector (from a Base class) and a Derivated class object, so later I am able to call a method for all. However I want to call aswell methods from Derivated classes so I need to store the reference for them aswell.
class Foo
{
vector<unique_ptr<Base>> bar;
unique_ptr<Derivated1> bar2;
unique_ptr<Derivated2> bar3;
}
Foo::Foo(){
this->bar2 = make_unique<Derivated1>();
this->bar2->doSomethingDerivated1();
this->bar3 = make_unique<Derivated2>();
this->bar->push_back(move(bar2));
this->bar->push_back(move(bar3));
}
Foo::callForAll() {
for (const auto& foo: this->bar) foo->doSomethingBase();
}
Foo::callForDerivated1() {
this->bar2->doSomethingDerivated1();
}
Is something like this possible? For my understanding this code will most likely fail. Will move place bar2 and bar3 to nullptr? Creating a unique_ptr, store a raw pointer with bar2->get() and then push_back to vector works?
Note: These objects only belong to this class, so unique would make sense.
No. The whole point of unique_ptr is to be unique. This means you cannot copy it.
However, you CAN make copies of the underlying pointer that unique_ptr manages. E.g.
unique_ptr<Foo> foo(new Foo);
Foo* foo_copy = foo.get();
There are a couple things that you need to be careful of when doing this:
Do not delete foo_copy. That is the job of unique_ptr. If you delete foo_copy, then you will have committed the sin of double delete, which has undefined behavior (i.e. the compiler is allowed to generate code that launches a nuclear missile).
Do not use foo_copy after foo has been destroyed because when foo is destroyed, the underlying pointer is deleted (unless foo has relinquished ownership of the underlying pointer, and the underlying pointer hasn't been deleted by some other means yet). This is the sin of use after free, and it also has UB.
Moving is one way for unique_ptr to relinquish ownership. Once you move out of a unique_ptr, it no longer points to anything (that is the whole point of moving; when you walk from A to B, you are no longer at A, because there is only one of you, and you have decided to instead be located at B). I believe that trying to call a method using the -> operator on an empty unique_ptr is also UB.
It seems like what you should do is
vector<unique_ptr<Base>> v;
Derived* ob = v[i].get();
Let me reiterate that this is slightly dangerous and unusual.
Tangent: I find it highly suspicious that you are not using virtual methods; virtual really should be the default (kind of like how double is the default, not float, even though float looks like it is and should be the default). Actually, I find it suspicious that you are using inheritance. Inheritance is one of the most over-rated features of all time. I suspect that this is where your troubles may be originating. For example, the Go language doesn't even have inheritance, yet it does have polymorphism (i.e. different implementations of the same interface).
PS: Please, do not accidentally extinguish the human race by invoking UB.
// Example program
#include <iostream>
class Foo{
public:
Foo(int a):a(a){}
void print(){
printf("%d\n",a);
}
private:
int a;
};
class Bar{
public:
Bar(Foo* foo):foo(foo){}
void print(){
foo->print();
}
private:
Foo* foo;
};
int main()
{
Foo f = {10};
Bar b(&f);
b.print();
f = {20};
b.print();
}
In the code above a Foo object shared with a Bar object can be recreated without that Bar knows about it.
Imagine I have to inject the bar object into a third class. Now I can update the foo dependency without having to create a new object of bar and the third class.
Is this pattern commonly used or not and does it violate some of the OOP principles?
I don't think the code does what you think it does.
I've added the default constructors and assign/operators to your Foo class with some logging to see what happens. These constructors are added automatically by the compilers unless you disable them explicitly. See the output here.
What happens in
f = {20};
is that you construct a different Foo object then you move-assign it to the original instance.
In this case it's equivalent to
f.a = 20; // Assuming we make a public.
In conclusion.
If your usage is just to change fields in the existing instance (through assign operators in this case). Then everything should work fine. This shouldn't necessarily invalidate OOP principles, unless you have assumptions that Bar.foo is constant or doesn't change. This is usually called composition and it's fairly common (your UI will contain various button instances that might be modified from other sources).
If you expect to change the implementation (say Foo is a virtual class and you want a different derivation to be substituted) then in your code you will need to have Foo* f = new Foo(10);. You will have copy of the pointer in b and the assignment will create a new class, that will not be update in b (something like f = new FooDerived(20);.
To make it work you need a Provider class (this is a OOP pattern). This would be something that gives you a Foo. The simplest one would be Foo**. But it's likely better to have something a bit more customizable.
That said for any serious work try to stay away from naked pointers (Foo*). Use unique_ptr or shared_ptr as appropriate to save yourself a lot of problems in the future.
Is this pattern commonly used or not and does it violate some of the OOP principles?
Yes, this is fairly common, and OK in your example.
You do have to be careful to ensure that f remains alive for the whole lifetime of b, which is the case in your example. If you were to copy b, you would also need to ensure the copy didn't outlive f.
The nice thing about the local variables of a function func is that they outlive any local variables of functions that func calls. Thus the local variables of main live for (almost) the whole program, only global variables outlive them.
Is this pattern commonly used or not and does it violate some of the OOP principles?
I would say that such a structure should be carefully used.
Actually, in Bar you are just copying the pointer value. But if the given Foo created on the stack goes out of scope, then Bar is storing a dangling pointer.
Trying to dereference a dangling pointer is Undefined Behaviour.
Is it bad to recreate stack object after injected to class as pointer?
Actually, as #DanielLangr mentioned, you did not have "recreated" the object, you just have reassigned its contents, so the object lifetime has not ended.
In your case, you're still fine.
I'm learning C++ while I run into this situation, where I want to implement an equivalently efficient version in C++ of the following symbolic code in C.
<header.h>
struct Obj;
Obj* create(...);
void do_some_thing(Obj*);
void do_another_thing(Obj*);
void destroy(Obj*);
The requirements are:
The implementation is provided in a library (static/dynamic) and the
header doesn't expose any detail other than the interface
It should be equally efficient
Exposing an interface (COM-like) with virtual functions doesn't qualify; that's a solution to enable polymorphism (more than one implementation exposed through the same interface) which isn't the case, and since I don't need the value it brings, I can't see why I should pay the cost of calling functions through 2 indirect pointers.
So my next thought was the pimpl idiom:
<header.h>
class Obj {
public:
Obj();
~Obj();
void do_some_thing();
void do_another_thing();
private:
class Impl;
smart_ptr<Impl> impl_; // ! What should I use here, unique_ptr<> or shared_ptr<> ?
};
shared_ptr<> doesn't seem to qualify, I would pay for unnecessary interlocked increment/decrement that didn't exist in the original implementation.
On the other hand unique_ptr<> makes Obj non-copyable. This means that the client can't call his own functions that take Obj by value, and Obj is merely a wrapper for a pointer, so essentially he can't pass pointers by value! He could do that in the original version. (passing by reference still doesn't qualify: he's still passing a pointer to a pointer)
So what should be the equally efficient way to implement this in C++?
EDIT:
I gave it some more thought and I came to this solution:
<header.h>
class ObjRef // I exist only to provide an interface to implementation
{ // (without virtual functions and their double-level indirect pointers)
public:
ObjRef();
ObjRef(ObjRef); // I simply copy pointers value
ObjRef operator=(ObjRef); // ...
void do_some_thing();
void do_another_thing();
protected:
class Impl;
Impl* impl_; // raw pointer here, I'm not responsible for lifetime management
};
class Obj : public ObjRef
{
Obj(Obj const&); // I'm not copyable
Obj& operator=(Obj const&); // or assignable
public:
Obj(Obj&&); // but I'm movable (I'll have to implement unique_ptr<> functionality)
Obj& operator=(Obj&&);
Obj();
~Obj(); // I destroy impl_
// and expose the interface of ObjRef through inheritance
};
Now I return to client Obj, and If client needs to distribute the usage of Obj by calling some other his functions, he can declare them as
void use_obj(ObjRef o);
// and call them:
Obj o = call_my_lib_factory();
use_obj(o);
Why not keep the C original? The reason that you didn't have to pay the reference counting premium in the C version is that the C version relied on the caller to keep any tally of the number of copies of Obj* in use.
By trying to ensure that the replacement is both copyable and that ensure that the underlying destroy method is only called once the last reference is destroyed you are imposing additional requirements over the original, so it is only natural that the proper solution (which seems to me to be shared_ptr) has some limited additional expense over the original.
I assume there's a reason why you need the a pointer to the object in the first place. Because the simplest, and most efficient approach, would be to just create it on the stack:
{
Obj x(...);
x.do_some_thing();
x.do_another_thing();
} // let the destructor handle `destroy()` when the object goes out of scope
But say you need it created on the heap, for whatever reason, most of it is just as simple, and just as efficient:
{
std::unique_ptr<Obj> x = Obj::create(...); // if you want a separate `create` function
std::unique_ptr<Obj> x = new Obj(...); // Otherwise, a plain constructor will do
x->do_some_thing();
x->do_another_thing();
} // as before, let the destructor handle destruction
There is no need for inheritance or interfaces or virtual functions. You're writing C++, not Java. One of the fundamental rules of C++ is "don't pay for what you don't use". C++ is as performant as C by default. You don't have to do anything special to achieve good performance. All you have to do is not use the features which have a performance cost if you don't need them.
You didn't need reference counting in your C version, so why would you use reference counting in the C++ version (with shared_ptr)? You didn't need the functionality that virtual functions provide in the C version (where it would be implemented through function pointers), so why would you make anything virtual in the C++ function?
But C++ lets you tidy up the create/destroy stuff in particular, and that costs you nothing. So use that. Create the object in its constructor, and let its destructor destroy it. And just place the object in an appropriate scope, so it'll go out of scope when you want it destroyed. And it gives you nicer syntax for calling "member" functions, so make use of that too.
On the other hand unique_ptr<> makes Obj non-copyable. This means that the client can't call his own functions that take Obj by value, and Obj is merely a wrapper for a pointer, so essentially he can't pass pointers by value! He could do that in the original version. (passing by reference still doesn't qualify: he's still passing a pointer to a pointer)
The client can take Obj by value if you use move semantics. But if you want the object to be copied, then let it be copied. Use my first example, and create the object on the stack, and just pass it by value when it needs to be passed by value. It it contains any complex resources (such as pointers to allocated memory), then be sure to write an appropriate copy constructor and assignment operator, and then you can create the object (on the stack, or wherever you need it), pass it around as you desire, by value, by reference, by wrapping it in a smart pointer, or by moving it (if you implement the necessary move constructor and move assignment operator).
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.
I use shared_ptr in my application design, and I have tendency that more and more objects become heap-allocated instead of to be a simple objects on stack (or agregates of more complex objects).
Instead of simple (but with risk that Foo::bar will become dangling reference in more complex situation) ...
struct Bar { };
struct Foo { Foo(Bar& bar) : bar(bar) { }; Bar& bar; };
int main() {
Bar bar;
Foo foo(bar);
// ...
}
... I need to do ...
struct Bar { };
struct Foo { Foo(shared_ptr bar) : bar(bar) { }; shared_ptr<Bar> bar; };
int main() {
shared_ptr<Bar> bar = make_shared<Bar>();
Foo foo(bar);
// ...
}
... because I want to avoid of manual objects life-time tracking
Did I missed point in shared_ptr usage or this is pay for automatic life-time management ? Or maybe this is bad design sign ?
It is a question of your object life cycle. You should use shared_ptr when you really share an object between multiple other objects.
In your case the owner of FOO and BAR must control the lifecycle of both. Maybe it is possible to make BAR a private member of you class FOO and let FOO control the life cycle.
I personally use the smart pointers to express the ownership of an object. Shared_ptr means that it is really shared and I am not the only owner of this object.
Scoped or unique pointer show that I am the only owner of the object. If you want to transfer the ownership you can use auto_ptr or the C++0x move semantics.
I have seen at least in bigger projects that the lack of life cycle control will lead to dangling objects. So you don't have a direct memory leak any longer because of automatic life-time management but you get circular dependencies. Which lead to the same result.
To answer your question if this is bad design. It depends on what you are doing.
It is a sign of bad design. shared_ptr exists for when your objects must be heap allocated. You should never additionally allocate anything on the heap just because you can use shared_ptr. The stack is still the best choice by miles.
You need to know before you start deciding how you're going to implement it, what objects need to go on the heap and which need to go on the stack, and what the ownership is. Then you can use shared_ptr as an implementation tool.
Have you tried working on values instead of pointers ?