I have recently attempted to learn how to use std::shared_ptr. When modifying my existing code I've found myself confused when allocating with member variables (outside of an initialisation list).
My old code:
Class A {
Base* member_var;
A() {
this->member_var = new Derived();
}
};
My new code:
Class A {
std::shared_ptr<Base> member_var;
A() {
//Note the shared_ptr is given type Derived, matching the object.
this->member_var = std::shared_ptr<Derived> (new Derived());
}
};
Is this correct? Or is this perhaps more correct?:
Class A {
std::shared_ptr<Base> member_var;
A() {
//Note the shared_ptr is of type Base, matching the member type.
this->member_var = std::shared_ptr<Base> (new Derived());
}
};
What is the difference between these two statements.
Worryingly, I can't seem to find any code examples of what I'm trying to do here. Is my approach to using std::shared_ptr wrong?
EDIT: Thanks to everyone for their help. I think I caused some confusion. For the sake of future readability, I'll expand on why I've chosen to take this approach. I chose to illustrate my question with a simple code example. In my actual problem, I don't use a Class A, I actually use a struct. The sole purpose of this struct, is to help me neatly hold on to a number of instances of various different objects. I frequently end up passing (by reference) each object individually, not the struct itself, as argument to functions. Furthermore, when I do give the entire struct as argument, I tend to pass-by-value this struct. Hence my interest in making these shared_ptr, not unique_ptr. I've been debating changing everything and encapsulating all these in a Class, like Class A in my example, and passing said instance of class pass-by-reference the object instance. In this instance, I agree with everyone who has commented, and unique_ptr seems more appropriate.
Of course there's no fundamental difference between a struct and a class. I just have a tendency to pass instances of structs by value (if all they contain are pointers), and instances of classes by reference. Perhaps that's a personal quirk of mine?
Regarding the use of polymorphism in the first place, there are two possible derived classes here, one of which is chosen at runtime. I wish to handle the base class, which is for all intents and purposes, an abstract class.
I'm still surprised this is not a more common situation. Perhaps the above paragraphs have highlighted further bad practice. In which case I would be grateful to hear about it.
I'd write it this way:
A() : member_var(std::make_shared<Derived>()) { }
In Modern C++ you should avoid using new whenever possible. If you cannot initialize your member_var in the initialization list, then do:
A()
{
// ...
member_var = std::make_shared<Derived>();
}
As mentioned by KerrekSB in the comments, I would also suggest considering whether you do indeed need shared ownership, or wheter a unique_ptr wouldn't be sufficient.
If that is the case, you should use a unique_ptr instead: in general, it is a good thing to express minimal requirements - this buys you performance and a better self-documenting code at the same time.
Unfortunately, in C++11 you sill have to resort to new to create a unique_ptr that points to a newly created object:
A() : member_var(new Derived()) { }
Or, if you cannot use initialization lists:
member_var.reset(new Derived());
On the other hand in C++14, which offers std::make_unique<>, I would rather write:
A() : member_var(std::make_unique<Derived>()) { }
Or, if you cannot use initialization lists:
member_var = std::make_unique<Derived>();
Related
Basically i have a one struct that contains objects to share between classes as following;
struct CoreComponents
{
std::unique_ptr<a> m_A = std::make_unique<a>();
std::unique_ptr<b> m_B;
std::unique_ptr<c> m_C = std::make_unique<c>();
};
And in my main class i own it via unique_ptr;
class Game
{
...
private:
std::unique_ptr<CoreComponents> m_Components;
...
};
Then i have other n classes which i need to access that m_Components object from it's functions without creating copies. (i will not modify contents of that object)
I tried using shared_ptr to hold m_Components in Game class then pass it to other classes (to their constructors) via value and store it but that scenario causes memory leaks. (i use memcheck for checking leaks) I found out that it's the cause of the leak but i couldn't figure out why exactly.
Shared_ptr scenario
Constructor of class which i need to access CoreComponents object;
GameScene::GameScene(std::shared_ptr<CoreComponents> components)
: m_Components(std::move(components))
I'm trying to hold it as member of GameScene class then use it in functions;
std::shared_ptr<CoreComponents> m_Components;
And this is how i pass it from inside of the Game class;
auto gs = std::make_unique<GameScene>(m_Components)
General usage inside GameScene class;
m_Components->m_A->draw(*m_OtherObjectInsideGameScene);
So what is the best way to create similar design using modern c++?
I was trying to avoid Singleton pattern but do i have to use it to achieve this or it's possible with better smart pointer usage?
PS: CoreComponents struct needs to be deleted from memory when Game class is destroyed.
It seems that you correctly separate the concerns of ownership and usage. The only trouble you have is how to forward the components to the rest of your system.
I would keep your owning structure, and create dedicated structures for the specific users:
struct CoreComponents {
unique_ptr<A> a; unique_ptr<B> b; ...
};
struct PartOfTheSystem {
void use(A& a, B& b);
};
struct Game {
CoreComponents components;
PartOfTheSystem user;
void stuff() {
user.use(*components.a, *components.b);
}
};
Yes: more typing.
But also: very clear logic: construction/ownership and use are separate concerns, and this is perfectly clear by design! Also refer to https://isocpp.github.io/CppCoreGuidelines/CppCoreGuidelines#Rr-smartptrparam.
The best way if you have shared objects is indeed to use a shared_ptr.
A unique_ptr is for unique ownership.
If you had memory leaks, it's time to investigate why that was, and fix them! Your report suggests a cyclical reference. Check for accidental lambda capture, and in some places you perhaps meant to use weak_ptr instead.
Using a singleton for this is like fixing your car's broken tyre by setting the whole thing on fire and taking a donkey instead. Your unique_ptr approach is more like fixing your car's broken tyre by removing it and driving on rims for the lols.
When a function needs to return an object. Should it return it through a pointer to derived or base?
class B{
}
class D:public B{
}
// way 1: return pointer to derived
D* createDerived(){
D* d = new D();
return d;
}
// way 2: return pointer to base
B* createDerived(){
B* d = new D();
return d;
}
I have heard of "program to an interface not an implementation" which would suggest that we should return a pointer to base. However my intuition says it is better in this case to return a pointer to derived, because if the client code uses base pointers, this function would still work! On the other hand, if we return pointer to base and the client code uses derived pointers, this would not work for them. It seems that by returning a more "specific" pointer, we are allowing more flexibility for client code.
Another way to look at it is from the perspective of "program by contract." One of the suggestions is to promise as little as you can. By promising that we will return a very specific object, we follow this rule. However if we return a base pointer, it seems to me that we are promising a lot more.
Which is better design? Is my reasoning above correct?
I have a lot to learn on how to make modular, maintainable, extensible software, so please excuse if my reasoning/conclusion is nooby. I am very interested in learning. Thank you so much for your time.
It isn't possible to answer this question in a general way. In particular, returning the more derived object imposes additional restrictions on future implementations of the method, while returning the base class imposes more restrictions on the caller. Which is best depends on the design of the application or library, and in particular the scope of functionality offered by B and D and the overall design of the API.
In general, you want to return the most-derived, or, loosely speaking, the most functional class, which doesn't constrain your future implementation choices. This allows your clients to use the return value efficiently, while still allowing you to the change the implementation in the future.
The primary downside of using the derived class D is that you expose more details to the client, which may be difficult or impossible to reverse later.
For example, imagine that that you have a method reverse(std::ReversibleContainer &cont), which takes a container and returns a reversed snapshot of it (i.e., changes to the underlying container don't effect the returned snapshot).
In your initial implementation, you might decide to implement this as:
template<class BidirectionalIterator>
std::list<T> reverse(BidirectionalIterator &start, BidirectionalIterator &end) {
std::vector output;
std::copy(input.begin(), input.end(), back_inserter(output))
return output;
}
Later on, you might realize that you can avoid the copy of the underlying data for certain cases where the container (and elements) are constant, for example:
ImmutableIterator reverse(ImmutableBiderectionalIterator &input) {
return ReversingImmutableBiderectionalIterator(input);
}
This container can use the knowledge that the input container is read-only to return a view of the input container, avoiding the copy, which simply remaps each access to result in the same semantics as a reversed container.
I suggest you to rename member functions to createB and createD and in second case return pointer to derived class, because you always can cast derived class pointer to base class, when reverse cast may fail.
The correct answer imo is neither. There is usually no need to return raw pointers from functions in your own code (exceptions below).
Instead, just return the created object itself:
class B { virtual ~B(){} };
class D : public B {};
// this function would make real sense only if D were a class template
auto createD()
{
return D{};
}
This suffices in about any cases. Moreover, and importantly, it expresses what you get, namely an object of type D which you can use as required. Instead, when you get a raw pointer, it's from the first (i.e. without guessing the behaviour from the function name, reading the documentation, etc.) unclear what you're allowed to do with this raw pointer. Can you wrap it inside a unique_ptr? Are you allowed to delete it? Unclear. Returning an object (or better, a well-designed object, which basically means consistent RAII) releases you from having to answer those question -- just do what you want with the object.
Further, if you really need the pointer (which is an abstraction from the object), you can still wrap the return inside a suitable smart pointer like
auto d_uptr = std::make_unique<D>(createDerived());
auto d_sptr = std::make_shared<D>(createDerived());
or, similarly, also into smart base class pointers,
std::unique_ptr<B> = std::make_unique<D>(createDerived());
std::shared_ptr<B> b_sptr = std::make_shared<D>(createDerived());
This uses copy elision to construct the pointees and produces no overhead as compared to your function returning a D*. Note that as a rule the pointer should be a smart pointer, because only then you are freed directly from the obligation of having to delete it correctly somewhere later in the code.
One exception where you need raw pointers as function return types is the clone pattern, which applies when you want to copy an object via a base class pointer. Here one should use smart pointers as well as the function invoked by the user, but inside the class one has to use raw pointers in order to allow for covariant return types of virtual functions:
class B
{
virtual ~B(){}
auto clone() const
{
return std::unique_ptr<B>(clone_impl());
}
protected:
virtual B* clone_impl() const = 0;
};
class D : public B
{
protected:
virtual D* clone_impl() const { return new D{*this}; };
};
There might be a lot of other exceptions (e.g. always when covariance is used) which I don't have in mind at the moment. But those are not that important imo.
Summarizing: don't use raw pointers as function return types unless you have a good reason to do so.
We can use Polymorphism (inheritance + virtual functions) in order to generalize different types under a common base-type, and then refer to different objects as if they were of the same type.
Using dynamic_cast appears to be the exact opposite approach, as in essence we are checking the specific type of an object before deciding what action we want to take.
Is there any known example for something that cannot be implemented with conventional polymorphism as easily as it is implemented with dynamic_cast?
Whenever you find yourself wanting a member function like "IsConcreteX" in a base class (edit: or, more precisely, a function like "ConcreteX *GetConcreteX"), you are basically implementing your own dynamic_cast. For example:
class Movie
{
// ...
virtual bool IsActionMovie() const = 0;
};
class ActionMovie : public Movie
{
// ...
virtual bool IsActionMovie() const { return true; }
};
class ComedyMovie : public Movie
{
// ...
virtual bool IsActionMovie() const { return false; }
};
void f(Movie const &movie)
{
if (movie.IsActionMovie())
{
// ...
}
}
This may look cleaner than a dynamic_cast, but on closer inspection, you'll soon realise that you've not gained anything except for the fact that the "evil" dynamic_cast no longer appears in your code (provided you're not using an ancient compiler which doesn't implement dynamic_cast! :)). It's even worse - the "self-written dynamic cast" approach is verbose, error-prone and repetitve, while dynamic_cast will work just fine with no additional code whatsoever in the class definitions.
So the real question should be whether there are situations where it makes sense that a base class knows about a concrete derived class. The answer is: usually it doesn't, but you will doubtlessly encounter such situations.
Think, in very abstract terms, about a component of your software which transmits objects from one part (A) to another (B). Those objects are of type Class1 or Class2, with Class2 is-a Class1.
Class1
^
|
|
Class2
A - - - - - - - -> B
(objects)
B, however, has some special handling only for Class2. B may be a completely different part of the system, written by different people, or legacy code. In this case, you want to reuse the A-to-B communication without any modification, and you may not be in a position to modify B, either. It may therefore make sense to explicitly ask whether you are dealing with Class1 or Class2 objects at the other end of the line.
void receiveDataInB(Class1 &object)
{
normalHandlingForClass1AndAnySubclass(object);
if (typeid(object) == typeid(Class2))
{
additionalSpecialHandlingForClass2(dynamic_cast<Class2 &>(object));
}
}
Here is an alternative version which does not use typeid:
void receiveDataInB(Class1 &object)
{
normalHandlingForClass1AndAnySubclass(object);
Class2 *ptr = dynamic_cast<Class2 *>(&object);
if (ptr != 0)
{
additionalSpecialHandlingForClass2(*ptr);
}
}
This might be preferable if Class2 is not a leaf class (i.e. if there may be classes further deriving from it).
In the end, it often comes down to whether you are designing a whole system with all its parts from the beginning or have to modify or adapt parts of it at a later stage. But if you ever find yourself confronted with a problem like the one above, you may come to appreciate dynamic_cast as the right tool for the right job in the right situation.
It allows you to do things which you can only do to the derived type. But this is usually a hint that a redesign is in order.
struct Foo
{
virtual ~Foo() {}
};
struct Bar : Foo
{
void bar() const {}
};
int main()
{
Foo * f = new Bar();
Bar* b = dynamic_cast<Bar*>(f);
if (b) b->bar();
delete f;
}
I can't think of any case where it's not possible to use virtual functions (other than such things as boost:any and similar "lost the original type" work).
However, I have found myself using dynamic_cast a few times in the Pascal compiler I'm currently writing in C++. Mostly because it's a "better" solution than adding a dozen virtual functions to the baseclass, that are ONLY used in one or two places when you already (should) know what type the object is. Currently, out of roughly 4300 lines of code, there are 6 instances of dynamic_cast - one of which can probably be "fixed" by actually storing the type as the derived type rather than the base-type.
In a couple of places, I use things like ArrayDecl* a = dynamic_cast<ArrayDecl*>(type); to determine that type is indeed an array declaration, and not someone using an non-array type as a base, when accessing an index (and I also need a to access the array type information later). Again, adding all the virtual functions to the base TypeDecl class would give lots of functions that mostly return nothing useful (e.g. NULL), and aren't called except when you already know that the class is (or at least should be) one of the derived types. For example, getting to know the range/size of an array is useless for types that aren't arrays.
No advantages really. Sometimes dynamic_cast is useful for a quick hack, but generally it is better to design classes properly and use polymorphism. There may be cases when due to some reasons it is not possible to modify the base class in order to add necessary virtual functions (e.g. it is from a third-party which we do not want to modify), but still dynamic_cast usage should be an exception, not a rule.
An often used argument that it is not convenient to add everything to the base class does not work really, since the Visitor pattern (see e.g. http://sourcemaking.com/design_patterns/visitor/cpp/2) solves this problem in a more organised way purely with polymorphism - using Visitor you can keep the base class small and still use virtual functions without casting.
dynamic_cast needs to be used on base class pointer for down cast when member function is not available in base class, but only in derived class. There is no advantage to use it. It is a way to safely down cast when virtual function is not overridden from base class. Check for null pointer on return value. You are correct in that it is used where there is no virtual function derivation.
What is the best method to go about passing a shared_ptr of a derived type to a function that takes a shared_ptr of a base type?
I generally pass shared_ptrs by reference to avoid a needless copy:
int foo(const shared_ptr<bar>& ptr);
but this doesn't work if I try to do something like
int foo(const shared_ptr<Base>& ptr);
...
shared_ptr<Derived> bar = make_shared<Derived>();
foo(bar);
I could use
foo(dynamic_pointer_cast<Base, Derived>(bar));
but this seems sub-optimal for two reasons:
A dynamic_cast seems a bit excessive for a simple derived-to-base cast.
As I understand it, dynamic_pointer_cast creates a copy (albeit a temporary one) of the pointer to pass to the function.
Is there a better solution?
Update for posterity:
It turned out to be an issue of a missing header file. Also, what I was trying to do here is considered an antipattern. Generally,
Functions that don't impact an object's lifetime (i.e. the object remains valid for the duration of the function) should take a plain reference or pointer, e.g. int foo(bar& b).
Functions that consume an object (i.e. are the final users of a given object) should take a unique_ptr by value, e.g. int foo(unique_ptr<bar> b). Callers should std::move the value into the function.
Functions that extend the lifetime of an object should take a shared_ptr by value, e.g. int foo(shared_ptr<bar> b). The usual advice to avoid circular references applies.
See Herb Sutter's Back to Basics talk for details.
This will also happen if you've forgotten to specify public inheritance on the derived class, i.e. if like me you write this:
class Derived : Base
{
};
Instead of:
class Derived : public Base
{
};
Although Base and Derived are covariant and raw pointers to them will act accordingly, shared_ptr<Base> and shared_ptr<Derived> are not covariant. The dynamic_pointer_cast is the correct and simplest way to handle this problem.
(Edit: static_pointer_cast would be more appropriate because you're casting from derived to base, which is safe and doesn't require runtime checks. See comments below.)
However, if your foo() function doesn't wish to take part in extending the lifetime (or, rather, take part in the shared ownership of the object), then its best to accept a const Base& and dereference the shared_ptr when passing it to foo().
void foo(const Base& base);
[...]
shared_ptr<Derived> spDerived = getDerived();
foo(*spDerived);
As an aside, because shared_ptr types cannot be covariant, the rules of implicit conversions across covariant return types does not apply when returning types of shared_ptr<T>.
Also check that the #include of the header file containing the full declaration of the derived class is in your source file.
I had this problem. The std::shared<derived> would not cast to std::shared<base>. I had forward declared both classes so that I could hold pointers to them, but because I didn't have the #include the compiler could not see that one class was derived from the other.
Sounds like you're trying too hard. shared_ptr is cheap to copy; that's one of its goals. Passing them around by reference doesn't really accomplish much. If you don't want sharing, pass the raw pointer.
That said, there are two ways to do this that I can think of off the top of my head:
foo(shared_ptr<Base>(bar));
foo(static_pointer_cast<Base>(bar));
Hallo,
I come from a C# background and don't have a lot of C++ experience. To produce clean code I try to separate implementation and interfaces and use inheritance when possible. And when I tried to apply typical C# concepts to C++ I ran into a problem that I've been unable to resolve so far. I assume that this is probably trivial for an experienced C++ programmer but it has been driving me crazy for quite a while.
First I declare a base class (it contains no logic at the moment but it will in the future)
class PropertyBase : public IProperty
{
};
Then I define an interface for the Properties
class IProperty
{
public:
virtual ~IProperty() {};
virtual PropertyBase correct(const ICorrector &corrector) = 0;
virtual PropertyBase joinWith(const PropertyBase &partner, const IRecombinator &recombinator) = 0;
};
This is where the problem comes in: The compiler returns errors for the two virtual functions saying that it is not allowed to declare a function that returns an abstract class. Of course I don't want to return an object of the type PropertyBase. I want to declare other classes that inherit from PropertyBase that return an instance of themselves.
Now I've read that a possible way around it is to modify IProperty like this to return pointers:
class IProperty
{
public:
virtual ~IProperty() {};
virtual PropertyBase* correct(const ICorrector &corrector) = 0;
virtual PropertyBase* joinWith(const PropertyBase &partner, const IRecombinator &recombinator) = 0;
};
However I would like to avoid this if possible to prevent memory leaks. It would be great if someone would have a better idea to deal with this problem.
Thank you very much
If you're afraid of memory leaks, switch to smart pointers. That has the additional benefit of being self-documenting wrt. ownership of the returned object.
class IProperty
{
public:
virtual ~IProperty() {};
virtual std::unique_ptr<PropertyBase> correct(const ICorrector &) = 0;
virtual std::unique_ptr<PropertyBase> joinWith(const PropertyBase &,
const IRecombinator &) = 0;
};
In your client code:
std::unique_ptr<PropertyBase> pb(property.correct(corrector));
// use pb and forget about it; smart pointers do their own cleanup
Or, if you want reference counting on the object:
std::shared_ptr<PropertyBase> pb(property.correct(corrector));
See MSDN docs for unique_ptr, shared_ptr.
This may not be the answer you're looking for, but it seems to me that you are a little confused about pointers and values in C++.
You have to return either a pointer, or a reference, in C++ if you want proper ad-hoc polymorphism. In this case, the compiler issued an error, because the base class was abstract. If instantiating an abstract class would be possible, it would have "holes" in it.
The thumb rule is: Whenever you have a class hierarchy, never return objects of such types by value. Suppose you have class Base { int x; }, and class Derived : public Base { int y; }. If you do this:
Base Function() { Derived d; return d; }
...
Base b = Function();
Then b will not be a value of class Derived "hiding behind" a Base. The value b WILL be Base. The compiler will "slice off" the differences between Derived and Base, and put it into b.
In C++, you will have to use pointers or references to facilitate ad-hoc polymorphism. References in C# is pretty much the same thing as pointers in C++, with the exception that you do not have to free the objects in C#, as the garbage collector will handle this for you.
There's nothing wrong with returning a pointer to an object. If you're worried about memory leaks, as you should be, the solution is to use smart pointers to store the returned pointer. The most flexible of these is shared_ptr from boost or the upcoming C++0x standard.
More generally, if you're going to be doing any serious amount of work in C++, getting comfortable with pointers and memory management is kind of essential. For in-depth coverage of that and other tricky aspects of C++, I strongly recommend the Effective C++ books by Scott Meyers and the Exceptional C++ books by Herb Sutter.
There is very easy solution to this problem. Use pointers or references for return values, but instead of returning ownership in the pointers, you should not return ownership.
For example:
class A : public Base
{
public:
Base *correct(const I &c)
{ p2 = do_something(c); return &p2; }
...
private:
A2 p2;
};
What makes this work is that you store the p2 inside the class and never pass ownership of the objects to outside of it. The function in the interface will not create new objects, but instead it'll just return existing one, configured to correct state based on function's parameters. This is a good alternative to the unique_ptr and shared_ptr solution which relies on heap allocation and creating new objects and passing them around.
Now the nice trick with this is that you need to list all possible types you want to return from your correct() function in the data members of the class. For example, if sometimes you would return different type, it'd look like this:
class B : public Base
{
public:
Base *correct(const I &c) {
switch(c.get_bool()) {
case false: p3 = do_something_else(c); return &p3;
case true: p4 = do_something(c); return &p4;
};
}
private:
B3 p3;
B4 p4;
};
But placing your objects p3 and p4 inside the current B object will solve this problem completely.