Как вернуть ссылку или копию

У меня есть следующий код:

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 ++.

0

Решение

Это просто возможный способ сделать это: в вашем классе 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 и предоставьте функцию «IsEmpty ()» для EdgeSet.

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;
}
static EdgeSet emptySet;
return emptySet;
}
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;
}
return 0;
}

В качестве альтернативы, вернуть boost::optional<EdgeSet&> который может быть пустым.

Но вы не должны возвращать ссылку «просто потому, что», вы должны возвращать ссылку, если вы хотите, чтобы вызывающая сторона могла ссылаться на тот же объект, который хранится на карте, а также иметь возможность изменять его. В противном случае было бы лучше вернуть копию или, возможно, ссылку на const.

0

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