如何返回引用或副本

How to return reference or copy

本文关键字:引用 副本 返回 何返回      更新时间:2023-10-16

我有以下代码:

EdgeSet Graph::GetNodeOutcomingEdges(long long NodeId) {
    //NodeEdgeMap is an unordereded_map
    NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
    if (it != NodeOutcomingEdges.end()) {
        return *(*(it)).second;
    }
    return EdgeSet();
}

然后. .

EdgeSet& OutcomingEdges = RoadGraph.GetNodeOutcomingEdges(Expandee.GetId());

因为值不一定在映射中,所以我必须以某种方式解释它,在理想情况下,返回一个空的(新)EdgeSet。我可以抛出异常,但有必要吗?这在VS下可以很好地编译(可能已经解释了RVO),但在g++中就不是这样了。

EdgeSet& Graph::GetNodeOutcomingEdges(long long NodeId) {
    //NodeEdgeMap is an unordereded_map
    NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
    if (it != NodeOutcomingEdges.end()) {
        return *(*(it)).second;
    }
    static EdgeSet emptySet;
    return emptySet;
}

这只是一种可能的方法:在您的Graph类中,定义EdgeSet类型的空成员变量,并使用一些将其标识为空的属性,例如"mEmptyFlag"布尔值:

class Graph {
   ...
   static EdgeSet mEmptyNode(params defining empty node here);
   ...
}
EdgeSet Graph::GetNodeOutcomingEdges(long long NodeId) {
    //NodeEdgeMap is an unordereded_map
    NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
    if (it != NodeOutcomingEdges.end()) {
        return *(*(it)).second;
    }
    return Graph::mEmptyNode;
}
callerFunct {
     EdgeSet& OutcomingEdges = RoadGraph.GetNodeOutcomingEdges(Expandee.GetId());
     if (OutcomingEdges.mEmptyflag==true) {
            deal with empty node here
     } else {
          ....
     }
 }

或者更好的封装,隐藏mEmptyFlag并为EdgeSet提供"IsEmpty()"函数。

假设您实际上想要返回一个引用,以允许调用者修改返回的对象,您可以返回一个指向已找到对象的指针,或者如果未找到则返回一个空指针:

EdgeSet* Graph::GetNodeOutcomingEdges(long long NodeId) {
    //NodeEdgeMap is an unordereded_map
    NodeEdgeMap::iterator it = NodeOutcomingEdges.find(NodeId);
    if (it != NodeOutcomingEdges.end()) {
        return it->second;
    }
    return 0;
}

或者,返回一个可以为空的boost::optional<EdgeSet&>

但是你不应该"仅仅因为"返回一个引用,如果你希望调用者能够引用存储在映射中的相同对象,并且能够修改它,你应该返回一个引用。否则,返回一个副本或const引用会更好。

NodeEdgeMap::iterator Graph::GetNodeOutcomingEdges(long long NodeId) {
    return NodeOutcomingEdges.find(NodeId);
}