Вот функция getValue (имя строки) из класса Map, который я использую в своей программе. Класс Map хранит строки как ключ и ValueType как значения.
template <typename ValueType>
ValueType Map<ValueType>::getValue(string key)
{
if (containsKey(key))
return (*this)[key];
Error("Attempt to getValue for key which is not contained in map.");
return ValueType(); // this code is never reached, but here to placate compiler
}
В файле graph.h я использую Map для хранения узлов (реализация класса узлов ниже), отображаемых там именами.
Файл graph.h
#ifndef GRAPH_H
#define GRAPH_H
#include "node.h"
#include "map.h"
class Graph{
public :
Graph();
~Graph();
void addNode(string name, double x, double y);
Node* getNode(string name);
private :
Map<Node> nodes;
};
Graph::Graph(){}
Graph::~Graph(){}
void Graph::addNode(string name, double x, double y){
if(!nodes.containsKey(name)){
Node n(name, x, y);
nodes.add(name, n);
}
}
Node* Graph::getNode(string name){
if(nodes.containsKey(name)){
return (&nodes.getValue(name));
}else{
Error ("No node with that name exists");
}
}
#endif
Класс узла
#ifndef NODE_H
#define NODE_H
class Node{
public:
Node();
~Node();
Node(string nodename, double nodeX, double nodeY);
void toString();
private:
string name;
double x,y;
};
Node::Node(){}
Node::~Node(){}
Node::Node(string nodename, double nodeX, double nodeY){
name = nodename;
x = nodeX;
y = nodeY;
}
void Node::toString(){
cout<<"Name "<<name<<", Location "<<x<<", "<<y<<endl;
}
#endif
Я пытаюсь создать указатель на объект узла, который извлекается с карты
Но возвращаемый указатель задает значение имени string name
varaible пустым.
В файле main.cpp
Graph g;
g.addNode("0COOL",42,42);
Node *n = g.getNode("0COOL");
n->toString();
Вывод вышеуказанного кода
Имя, местонахождение 42, 42
Почему поле имени опущено?
Проблема в том, что ваша Map<ValueType>::getValue(string key)
возвращает результат по значению. Когда вы это сделаете
return (&nodes.getValue(name));
вы возвращаете указатель на временную переменную, созданную компилятором для хранения результата getValue
. Развертывание этого указателя позже является неопределенным поведением, поскольку объект, на который указывает временный объект, уничтожается при выходе из функции Graph::getNode(string name)
.
Чтобы устранить эту проблему, верните ValueType
из Map<ValueType>::getValue(string key)
по ссылке. Это ограничило бы время жизни указателя на время жизни соответствующего элемента на карте. Конечно, вам нужно убедиться, что во всех случаях есть верная ссылка на возврат - в частности, это не будет законным: return ValueType()
. Вам нужно будет создать статическую переменную для представления отсутствующего значения и вернуть ссылку на нее, когда значение не будет найдено.