为什么 getNodeSuccess 方法有效,但 getNodeFail 方法无效?
Why does the method getNodeSuccess work, but not getNodeFail?
我对以下代码的行为感到困惑:我不明白为什么 getNodeSuccess
方法有效,但 getNodeFail
方法无法构建。这两种方法之间的唯一区别是,一种使用 []
运算符访问地图,另一种使用 at
方法。我认为这两个操作都返回对地图中元素的引用,并且两者基本上应该做同样的事情。但是,当我使用 []
运算符而不是 at()
方法时,它会尝试调用 GraphNode class 的默认构造函数。由于默认构造函数是私有的,因此构建失败。
为了演示,我将 GraphNode
class 的默认构造函数设为私有。如果我将其更改为 public,它就会起作用。
有人可以解释一下这是怎么回事吗?为什么一种方法触发默认构造函数,而另一种方法不触发?
#include <vector>
#include <list>
#include <unordered_map>
#include <exception>
template <class T>
struct GraphNode
{
int id;
T data;
std::list<int> adj; // adjacency list
GraphNode(const int id)
{
this->id = id;
}
private:
GraphNode() {}
};
template<class T>
struct UndirectedGraph
{
std::unordered_map<int, GraphNode<T>> lookup;
std::vector<GraphNode<T>> vertices;
void addNode(const GraphNode<T> node)
{
// if the id of the node already exists, than we cannot add it
if (lookup.find(node.id) == lookup.end())
lookup.insert(std::make_pair(node.id, node));
else
throw std::runtime_error("Trying to add a node that already exists.");
}
void addEdge(const int source, const int destination)
{
getNodeSuccess(source).adj.push_back(destination);
getNodeSuccess(destination).adj.push_back(source);
getNodeFail(source).adj.push_back(destination);
getNodeFail(destination).adj.push_back(source);
}
GraphNode<T>& getNodeSuccess(const int id)
{
if (lookup.find(id) == lookup.end())
throw std::runtime_error("Trying to retrieve a node that doesn't exist");
return lookup.at(id);
}
GraphNode<T>& getNodeFail(const int id)
{
if (lookup.find(id) == lookup.end())
throw std::runtime_error("Trying to retrieve a node that doesn't exist");
return lookup[id];
}
};
int main(int argc, char* argv[])
{
UndirectedGraph<int> graph;
graph.addNode(GraphNode<int>(1));
graph.addNode(GraphNode<int>(3));
graph.addEdge(1, 3);
return 0;
}
operator[]
将 return
对具有该键的值的引用,或者使用默认构造函数创建一个,插入它,然后 return
对新构造的值的引用.因此,您的问题是 operator[]
必须至少能够调用默认构造函数, 即使您知道密钥将始终存在 .
如果您只想查找您的 unordered_map
中是否有内容,您对 find
的使用已经结束。
GraphNode<T>& getNodeFail(const int id)
{
auto it = lookup.find(id);
if (it == lookup.end())
throw std::runtime_error("Trying to retrieve a node that doesn't exist");
return it->second;
}
这也将为您节省额外的查找,因为您已经使用 find
完成了一次工作。
我对以下代码的行为感到困惑:我不明白为什么 getNodeSuccess
方法有效,但 getNodeFail
方法无法构建。这两种方法之间的唯一区别是,一种使用 []
运算符访问地图,另一种使用 at
方法。我认为这两个操作都返回对地图中元素的引用,并且两者基本上应该做同样的事情。但是,当我使用 []
运算符而不是 at()
方法时,它会尝试调用 GraphNode class 的默认构造函数。由于默认构造函数是私有的,因此构建失败。
为了演示,我将 GraphNode
class 的默认构造函数设为私有。如果我将其更改为 public,它就会起作用。
有人可以解释一下这是怎么回事吗?为什么一种方法触发默认构造函数,而另一种方法不触发?
#include <vector>
#include <list>
#include <unordered_map>
#include <exception>
template <class T>
struct GraphNode
{
int id;
T data;
std::list<int> adj; // adjacency list
GraphNode(const int id)
{
this->id = id;
}
private:
GraphNode() {}
};
template<class T>
struct UndirectedGraph
{
std::unordered_map<int, GraphNode<T>> lookup;
std::vector<GraphNode<T>> vertices;
void addNode(const GraphNode<T> node)
{
// if the id of the node already exists, than we cannot add it
if (lookup.find(node.id) == lookup.end())
lookup.insert(std::make_pair(node.id, node));
else
throw std::runtime_error("Trying to add a node that already exists.");
}
void addEdge(const int source, const int destination)
{
getNodeSuccess(source).adj.push_back(destination);
getNodeSuccess(destination).adj.push_back(source);
getNodeFail(source).adj.push_back(destination);
getNodeFail(destination).adj.push_back(source);
}
GraphNode<T>& getNodeSuccess(const int id)
{
if (lookup.find(id) == lookup.end())
throw std::runtime_error("Trying to retrieve a node that doesn't exist");
return lookup.at(id);
}
GraphNode<T>& getNodeFail(const int id)
{
if (lookup.find(id) == lookup.end())
throw std::runtime_error("Trying to retrieve a node that doesn't exist");
return lookup[id];
}
};
int main(int argc, char* argv[])
{
UndirectedGraph<int> graph;
graph.addNode(GraphNode<int>(1));
graph.addNode(GraphNode<int>(3));
graph.addEdge(1, 3);
return 0;
}
operator[]
将 return
对具有该键的值的引用,或者使用默认构造函数创建一个,插入它,然后 return
对新构造的值的引用.因此,您的问题是 operator[]
必须至少能够调用默认构造函数, 即使您知道密钥将始终存在 .
如果您只想查找您的 unordered_map
中是否有内容,您对 find
的使用已经结束。
GraphNode<T>& getNodeFail(const int id)
{
auto it = lookup.find(id);
if (it == lookup.end())
throw std::runtime_error("Trying to retrieve a node that doesn't exist");
return it->second;
}
这也将为您节省额外的查找,因为您已经使用 find
完成了一次工作。