让我们以表示子节点树的数据结构(节点)为例。每个对象的子节点集存储在地图中>
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;
}
};
用户通常会调用以下代码示例。
NodePtr spNode, spChildNode;
bool result;
...
result = spNode->GetChildByKeyName(strChildKeyName, spChildNode);
到目前为止,一切都很好。
我突然想到,调用者可能会遍历树,而不必为树的每个深度处理额外的变量
NodePtr spNode;
bool result;
result = spNode->GetChildItem(strChildKeyName, spNode);
if (result)
spNode->GetChildItem(strSubKeyName, spNode);
在上述情况下,如果 spNode 是对该对象的最后剩余引用,那么我担心 GetChildItem 方法中的这段代码:
spChild = itor->second;
result = true;
SomeOtherMethod();
spChild(实际上是调用者的 spNode 实例)的分配是否会在上次引用刚刚消失后无意中破坏“this”节点?(因此在 spChild 分配之后调用其他方法是危险的)。我这里有潜在的错误吗?
我认为解决方法是在方法调用的顶部简单地添加这一行:
NodePtr spChildRef = spChild; // maintain a reference to the caller's original node during the scope of the method
想法?