Let's take the following example of a data structure (Node) that represents a tree of child nodes. The set of child nodes for each object is stored in a map>
class Node;
typedef std::shared_ptr<Node> NodePtr;
class Node
{
std::map<const std::string, NodePtr> _childNodes;
void SomeOtherMethod();
public:
bool GetChildByKeyName(/*In*/ const std::string& key, /*Out*/ NodePtr& spChild)
{
bool result = false;
auto itor = _childNodes.find(key);
if (itor != _childNodes.end())
{
spChild = itor->second;
result = true;
SomeOtherMethod();
}
return result;
}
};
And the following code sample as users would typically call it.
NodePtr spNode, spChildNode;
bool result;
...
result = spNode->GetChildByKeyName(strChildKeyName, spChildNode);
So far so good.
It occurred to me that callers might way to traverse the tree without having to deal with extra variables for each depth into the tree
NodePtr spNode;
bool result;
result = spNode->GetChildItem(strChildKeyName, spNode);
if (result)
spNode->GetChildItem(strSubKeyName, spNode);
In the above case, if spNode is the final remaining reference to the object, then I'm worried about this block of code in the GetChildItem method:
spChild = itor->second;
result = true;
SomeOtherMethod();
Does the assignment of spChild (which is really the caller's spNode instance) inadvertently destruct "this" Node since the last reference just went away? (And hence calling other methods after the spChild assignment is dangerous). Do I have a potential bug here?
I think the workaround is to simply add this line at the top of the method call:
NodePtr spChildRef = spChild; // maintain a reference to the caller's original node during the scope of the method
Thoughts?