To best explain this problem, I have constructed a simple example. Say I have a class Blob
as follows:
class Blob
{
string personalName;
string& familyName;
}
A Blob
can be spawned by the Creator (aka Programmer), at which point it gets to pick a personalName
and, since it has the privilege of being a 1st generation Blob
, it gets to pick it's own familyName
.
Alternatively, a Blob
can be created by spawning off an existing Blob
, at which point it picks its own personalName
, but shares a familyName
with all other Blob
s that have been cloned in this family. If one Blob
changes the family name, all other family members get that name change automatically.
So far, this sounds all well and good, until when writing the Blob
constructor I see this:
Blob::Blob() :
personalName(pickName()),
familyName(pickFamilyName())
{ }
...
string& Blob::pickFamilyName()
{
return *(new string("George"));
} // All Blobs have family name "George" in this example
Eek! Allocating memory on the heap then assigning it to a reference variable?! That looks scary!
Are my instincts correct that there is something very wrong with this, or does it only feel strange to me because it is not a common pattern? If there is something wrong, what is it? Why is this a bad design?
Note: It would be important to free that heap-allocated memory by reference counting and deleting the memory when the last Blob is destructed, or by some other method.
Heap references are always memory-preserving, which means that, as long as a heap reference points to an object or a part of an object, the object is not deleted by Garbage Collector.
Heap Allocation: Heap allocation is an allocation procedure in which the heap is used to manage the allocation of memory. Heap helps in managing dynamic memory allocation. In heap allocation, the creation of dynamic data objects and data structures is also possible as same as stack allocation.
Memory is allocated when a pointer is defined. A reference however, is a name alias & hence no memory is allocated for it( Is it correct? ). 2. Reference is bound to be initialized at the time of definition because, a reference is implemented with a constant pointer & hence cannot be made to point to the other object.
Heap follows dynamic memory allocation scheme (memory is allocated during execution or at runtime) and provides random and global access to objects created, unlike stack, which follows Last-In-First-Out (LIFO) memory access order. The size of heap memory is large when compared to stack.
The only time it makes sense to store a reference as a class member is when:
Your example violates rule 1.
I think the "smelly" part of it is storing the variable as a reference to a string, since it can become difficult to keep track of whether it's a valid object. Why not use something like:
boost::shared_ptr<std::string> Blob::pickFamilyName()
{
return boost::shared_ptr<std::string>(new std::string("George"));
}
EDIT
As per Praetorian's suggestion, you can avoid manually allocating memory yourself altogether:
boost::shared_ptr<std::string> Blob::pickFamilyName()
{
return boost::make_shared<std::string>("George");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With