如何返回引用或复制

时间:2014-03-13 12:42:31

标签: c++ reference

我有以下代码:

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 ++不是这样。

4 个答案:

答案 0 :(得分:1)

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;
}

答案 1 :(得分:0)

假设您确实想要返回引用,以允许调用者修改返回的对象,您可以返回指向找到的对象的指针,或者如果找不到它则返回空指针:

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&>,可以为空。

但是你不应该返回引用&#34;只是因为&#34;,如果你希望调用者能够引用存储在地图中的相同对象,你应该返回引用,并且也能够修改它。否则,返回副本或const引用会更好。

答案 2 :(得分:0)

这只是一种可行的方法:在Graph类中,定义一个EdgeSet类型的空成员变量,其中一些属性将其标识为空,例如“mEmptyFlag”boolean:

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()”函数。

答案 3 :(得分:-3)

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