I have an abstract class, CAbstract, and want to have a member of this type in another class, CClass. If I make it a pointer, I will have to take care of the deleting myself, and do would like to avoid this.
If I make it a reference, will it get deleted automatically when the CClass gets deleted?
Can I make it a shared_ptr? Can shared_ptr manage abstract classes and pointing to derived classes?
References don't automatically deallocate anything; shared_ptr does. As long as you follow the rules of C++, it should handle inheritance situations gracefully. More specifically, since shared_ptr's destructor calls delete by default when the reference count drops to zero, you need to implement the (virtual) destructor properly to make shared_ptr work.
Related
So I have the standard C++ setup with an object that stores another object. The stored object is owned completely, it's never leaked to the outside. The member is non-const.
class Container
{
private:
Contained item;
}
As I understand, when my Container is instantiated the default constructor will be called on the item member and I don't have to manage it in the initializer list.
Also do I understand it correctly that when my object is destroyed the dtor on the item will be called automatically?
Another option would be to store it by reference of course
class Container
{
private:
Contained& item;
public:
Container() : Contained()
{
}
}
in which case I don't know whether I should delete it in the dtor.
Yet another option is to store it by ptr
class Container
{
private:
Contained* item;
public:
Container()
{
item = new Contained();
}
~Container()
{
delete item;
}
}
Knowing that my item never gets returned to the caller and never bleeds into the outside API and never gets reassigned, what is the best way to proceed? As I mentioned, the item member is not const
(it will be a self-resizing data structure).
The easiest is to store the object itself. Using reference for this purpose is, I would say, confusing. One advantage with using the pointer is that you then may be able to avoid defining the Contained type in the header file - you can instead forward declare Contained, and keep all the details inside the .cpp file.
The first way is the best way in my opinion (it appears you don't need the object to be lazily constructed). The second way requires that you pass in the object from the outside and that it's lifetime is guaranteed, and the third way is really only good if you want lazy instantiation (i.e. only create the object on first use).
In this case, it's best to store the object itself, yes. Storing it by reference will only create an alias to the object, so your class is not the actual owner. Storing via a pointer is useless, unless your object is a base class and you might want to store a derived object.
Contrary to Luchian Grigore, I’d go for pointer/reference method: storing the encapsulated object as a reference or pointers lets you forward-declare it, hence saving compilation time.
In addition to that, it lets you have init() and destroy() member functions that would in turn call the constructor and destructors of the encapsulated object, as well as perform initialization of the other parts of the object. This way, a bad initialization can be handled by the return value of init().
Most of the time, you want to reduce the dependencies on your class. If this class forms an integral part of the interface (even if the member is private) then you can assume that anyone using your class will be using this one.
In such a case, having it as a member variable makes sense.
Where it is an implementation detail of your class, you should hide this detail from the users by using a forward declaration, so use a type that allows a forward declaration.
It is highly unlikely that it will be a reference. A reference must be initialsed on construction of your class, and so the constructor would probably have to pass in the object it refers to. Declaring it with new and dereferencing is going to lead to confusion.
If it is a pointer, your class can manage its lifetime with the destructor. In this case I often will use a raw pointer as it is well under control and my destructor can happily delete it, assuming my class is non-copyable.
If you use shared_ptr, you can use a forward declaration. But beware that your semantics are now that if you copy your object, all the copies will have a pointer to the same underlying object. If this is not what you want, shared_ptr is probably wrong. In addition, if you use shared_ptr when your class is non-copyable, it isn't really shared.
So unless you can use unique_ptr which allows a forward declaration, I would go for the raw pointer and a non-copyable class.
If your member does remain an implementation detail but is something that is pretty standard, like a map or a vector, it is not worth "encapsulating it" to the extent of using a forward declaration, only the types that are contained within the map or the vector, but not the map or vector itself.
Here is my issue:
My base class has a constructor that takes in a class pointer, if that pointer is NULL, it knows to instance it itself and maintain it.
The problem is, in the base destructor, I have to unregister that pointer with something private of base. So what happens is when I try to make a call to the class pointer in the base destructor and the derived is maintaining it, it has already been freed. So that causes a problem. What could I do?
Thanks
If the base class creates an instance for the pointer, why can't it free it as well? Is there anything stopping you from moving the free into the base destructor?
It's always best to be consistent in terms of who does what, at a certain level of hierarchy- splitting up the same responsibility across several levels of hierarchy will surely lead to problems such as this. Not to mention, if you want to create another class that inherits from base, you will have to re-implement this management in the new class as well, creating code duplication.
The order of constructors and destructors in inheritence is opposite; the base constructor is called before any of it's derived constructors. Upon delete, the inverse happens - the derived class is deleted first.
To solve your problem, could the base destructor not test whether its private instance is not NULL?
The base class could implement a protected member function to do the cleanup, then the derived destructor could call this helper function before destroying the resource.
From your description I gather that sometimes the derived class will be in charge of this pointer, and sometimes the base class will be. The simplest solution I can think of is to add a boolean in your base class that will allow you to track who owns the object. If the base class has initialized the pointer, set the boolean to true. Then your destructor can check who owns the object and in turn whether it should clean up.
A better solution would be to use boost:shared_ptr. This is a reference counting pointer abstraction that will automatically cleanup your object when its last reference goes out of scope. With this abstraction you generally don't need to worry about who releases your pointer.
If your constructor allocates memory, the corresponding destructor is responsible for freeing it. If you conditionally allocate memory, then you need to conditionally free it. A Boolean flag would help you determine if allocation occurred.
Another solution is to use a reference counting. At the time of the allocation the reference count shall be 1. If another class has interest in the object, it retains the pointer by increasing the reference count. If a class is no longer interested in the object, it decreases the reference count. When the counter reaches 0, the object must be deleted. shared_ptr is a standard C++ reference counted auto pointer implementation, which works very well in complex mixed ownership situations.
If I were to follow the RAII rule and would be developing a class in C++, would it be necessary to have static constructors? Will static constructors help me in any way or would be a wrong step to do?
That doesn't make any sense, you cannot have a static constructor. The entire purpose of the constructor is to initialize a specific instance of a class; if it were static, it wouldn't belong to any instance.
RAII just says that you need to free a resource in the destructor, and that the acquisition of that resource happens with the initialization (construction) of the object who will run that destructor. (Which entails you need a working or forbidden copy-constructor, along with a working assignment operator.)
I take it you are talking about a static factory function that creates an instance of your class (As others pointed out). In which case, you don't need to use the RAII pattern.
Remember you need your class to be stack allocated, so that the
constructor is called (automatically) and initializes various data.
also, the
destructor is called (automatically) when the stack unwinds and performs other operations: such as freeing resources etc..
If your class initializes it's data statically then the RAII pattern will fail, since statically held data is not bound to an instance of a class. So when the stack unwinds there is no instance to destruct, no destructor gets called, and the RAII pattern is not implemented.
You could have some static function CreateInstance() that would return you the instance of your class.
With RAII your function will probably have to return you some smart pointer to the instance you created to avoid copying of the actual object. Then you store this pointer, copy it if you need it in other places. When all smart pointers are destructed the object will be destructed too. If that's what you want, then yes - you could have "static constructor".
Of course it's not a must in RAII and normally would be just unneeded complication.
One of the thing that has been confusing for me while learning C++ (and Direct3D, but that some time ago) is when you should use a pointer member in a class. For example, I can use a non-pointer declaration:
private:
SomeClass instance_;
Or I could use a pointer declaration
private:
Someclass * instance_
And then use new() on it in the constructor.
I understand that if SomeClass could be derived from another class, a COM object or is an ABC then it should be a pointer. Are there any other guidelines that I should be aware of?
A pointer has following advantages:
a) You can do a lazy initialization, that means to init / create the object only short before the first real usage.
b) The design: if you use pointers for members of an external class type, you can place a forward declaration above your class and thus don't need to include the headers of that types in your header - instead of that you include the third party headers in your .cpp - that has the advantage to reduce the compile time and prevents side effects by including too many other headers.
class ExtCamera; // forward declaration to external class type in "ExtCamera.h"
class MyCamera {
public:
MyCamera() : m_pCamera(0) { }
void init(const ExtCamera &cam);
private:
ExtCamera *m_pCamera; // do not use it in inline code inside header!
};
c) A pointer can be deleted anytime - so you have more control about the livetime and can re-create an object - for example in case of a failure.
The advantages of using a pointer are outlined by 3DH: lazy initialization, reduction in header dependencies, and control over the lifetime of the object.
The are also disadvantages. When you have a pointer data member, you probably have to write your own copy constructor and assignment operator, to make sure that a copy of the object is created properly. Of course, you also must remember to delete the object in the destructor. Also, if you add a pointer data member to an existing class, you must remember to update the copy constructor and operator=. In short, having a pointer data member is more work for you.
Another disadvantage is really the flip side of the control over the lifetime of the object pointed to by the pointer. Non-pointer data members are destroyed automagically when the object is destroyed, meaning that you can always be sure that they exist as long as the object exists. With the pointer, you have to check for it being nullptr, meaning also that you have to make sure to set it to nullptr whenever it doesn't point to anything. Having to deal with all this may easily lead to bugs.
Finally, accessing non-pointer members is likely to be faster, because they are contiguous in memory. On the other hand, accessing pointer data member pointing to an object allocated on the heap is likely to cause a cache miss, making it slower.
There is no single answer to your question. You have to look at your design, and decide whether the advantages of pointer data members outweigh the additional headache. If reducing compile time and header dependencies is important, use the pimpl idiom. If your data member may not be necessary for your object in certain cases, use a pointer, and allocate it when needed. If these do not sound like compelling reasons, and you do not want to do extra work, then do not use a pointer.
If lazy initialization and the reduction of header dependencies are important, then you should first consider using a smart pointer, like std::unique_ptr or std::shared_ptr, instead of a raw pointer. Smart pointers save you from many of the headaches of using raw pointers described above.
Of course, there are still caveats. std::unique_ptr cleans up after itself, so you do not need to add or modify the destructor of your class. However, it is non-copiable, so having a unique pointer as a data member makes your class non-copiable as well.
With std::shared_ptr, you do not have to worry about the destructor or copying or assignment. However, the shared pointer incurs a performance penalty for reference counting.
Allocate it on the stack if you can, from the free-store if you have to. There is a similar question here, where you will find all the "why's".
The reason you see lots of pointer usage when it comes to games and stuff is because DirectX is a COM interface, and in honesty, most games programmers from back in the day aren't really C++ programmers, they are C-with-classes programmers, and in C pointer usage is very common.
Another reason to use pointers would be dynamic binding. If you have a base class with a virtual method and some derived classes, you can only get dynamic binding using pointers.
This is a simplified example to illustrate the question:
class A {};
class B
{
B(A& a) : a(a) {}
A& a;
};
class C
{
C() : b(a) {}
A a;
B b;
};
So B is responsible for updating a part of C. I ran the code through lint and it whinged about the reference member: lint#1725.
This talks about taking care over default copy and assignments which is fair enough, but default copy and assignment is also bad with pointers, so there's little advantage there.
I always try to use references where I can since naked pointers introduce uncertaintly about who is responsible for deleting that pointer. I prefer to embed objects by value but if I need a pointer, I use auto_ptr in the member data of the class that owns the pointer, and pass the object around as a reference.
I would generally only use a pointer in member data when the pointer could be null or could change. Are there any other reasons to prefer pointers over references for data members?
Is it true to say that an object containing a reference should not be assignable, since a reference should not be changed once initialised?
My own rule of thumb :
Use a reference member when you want the life of your object to be dependent on the life of other objects : it's an explicit way to say that you don't allow the object to be alive without a valid instance of another class - because of no assignment and the obligation to get the references initialization via the constructor. It's a good way to design your class without assuming anything about it's instance being member or not of another class. You only assume that their lives are directly linked to other instances. It allows you to change later how you use your class instance (with new, as a local instance, as a class member, generated by a memory pool in a manager, etc.)
Use pointer in other cases : When you want the member to be changed later, use a pointer or a const pointer to be sure to only read the pointed instance. If that type is supposed to be copyable, you cannot use references anyway. Sometimes you also need to initialize the member after a special function call ( init() for example) and then you simply have no choice but to use a pointer. BUT : use asserts in all your member function to quickly detect wrong pointer state!
In cases where you want the object lifetime to be dependent on an external object's lifetime, and you also need that type to be copyable, then use pointer members but reference argument in constructor That way you are indicating on construction that the lifetime of this object depends on the argument's lifetime BUT the implementation use pointers to still be copyable. As long as these members are only changed by copy, and your type don't have a default constructor, the type should fullfil both goals.
Avoid reference members, because they restrict what the implementation of a class can do (including, as you mention, preventing the implementation of an assignment operator) and provide no benefits to what the class can provide.
Example problems:
you are forced to initialise the reference in each constructor's initialiser list: there's no way to factor out this initialisation into another function (until C++0x, anyway edit: C++ now has delegating constructors)
the reference cannot be rebound or be null. This can be an advantage, but if the code ever needs changing to allow rebinding or for the member to be null, all uses of the member need to change
unlike pointer members, references can't easily be replaced by smart pointers or iterators as refactoring might require
Whenever a reference is used it looks like value type (. operator etc), but behaves like a pointer (can dangle) - so e.g. Google Style Guide discourages it
Objects rarely should allow assign and other stuff like comparison. If you consider some business model with objects like 'Department', 'Employee', 'Director', it is hard to imagine a case when one employee will be assigned to other.
So for business objects it is very good to describe one-to-one and one-to-many relationships as references and not pointers.
And probably it is OK to describe one-or-zero relationship as a pointer.
So no 'we can't assign' then factor.
A lot of programmers just get used with pointers and that's why they will find any argument to avoid use of reference.
Having a pointer as a member will force you or member of your team to check the pointer again and again before use, with "just in case" comment. If a pointer can be zero then pointer probably is used as kind of flag, which is bad, as every object have to play its own role.
Use references when you can, and pointers when you have to.
In a few important cases, assignability is simply not needed. These are often lightweight algorithm wrappers that facilitate calculation without leaving the scope. Such objects are prime candidates for reference members since you can be sure that they always hold a valid reference and never need to be copied.
In such cases, make sure to make the assignment operator (and often also the copy constructor) non-usable (by inheriting from boost::noncopyable or declaring them private).
However, as user pts already commented, the same is not true for most other objects. Here, using reference members can be a huge problem and should generally be avoided.
As everyone seems to be handing out general rules, I'll offer two:
Never, ever use use references as class members. I have never done so in my own code (except to prove to myself that I was right in this rule) and cannot imagine a case where I would do so. The semantics are too confusing, and it's really not what references were designed for.
Always, always, use references when passing parameters to functions, except for the basic types, or when the algorithm requires a copy.
These rules are simple, and have stood me in good stead. I leave making rules on using smart pointers (but please, not auto_ptr) as class members to others.
Yes to: Is it true to say that an object containing a reference should not be assignable, since a reference should not be changed once initialised?
My rules of thumb for data members:
never use a reference, because it prevents assignment
if your class is responsible for deleting, use boost's scoped_ptr (which is safer than an auto_ptr)
otherwise, use a pointer or const pointer
I would generally only use a pointer in member data when the pointer could be null or could change. Are there any other reasons to prefer pointers over references for data members?
Yes. Readability of your code. A pointer makes it more obvious that the member is a reference (ironically :)), and not a contained object, because when you use it you have to de-reference it. I know some people think that is old fashioned, but I still think that it simply prevent confusion and mistakes.
I advise against reference data members becasue you never know who is going to derive from your class and what they might want to do. They might not want to make use of the referenced object, but being a reference you have forced them to provide a valid object.
I've done this to myself enough to stop using reference data members.