为啥方法 getNodeSuccess 有效,但 getNodeFail 无效?

Posted

技术标签:

【中文标题】为啥方法 getNodeSuccess 有效,但 getNodeFail 无效?【英文标题】:Why does the method getNodeSuccess work, but not getNodeFail?为什么方法 getNodeSuccess 有效,但 getNodeFail 无效? 【发布时间】:2020-03-24 04:01:38 【问题描述】:

我对以下代码的行为感到困惑:我不明白为什么 getNodeSuccess 方法有效,但 getNodeFail 方法无法构建。这两种方法之间的唯一区别是一种使用[] 运算符来访问地图,另一种使用at 方法。我认为这两个操作都返回了对地图中元素的引用,并且两者基本上都应该做同样的事情。但是,当我使用 [] 运算符而不是 at() 方法时,它会尝试调用 GraphNode 类的默认构造函数。由于默认构造函数是私有的,因此构建失败。

为了演示,我将GraphNode 类的默认构造函数设为私有。如果我将其更改为公开,则它可以工作。

有人能解释一下这里发生了什么吗?为什么一种方法会触发默认构造函数,而不是另一种?

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

【问题讨论】:

【参考方案1】:

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 无效?的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 User::first() 上调用方法有效,但 User::where(...) 无效?

“Python 线程障碍”为啥这段代码有效,有没有更好的方法?

为啥一种方法比另一种更有效?

为啥铸造给CS0030,而“as”有效?

为啥 VS Code 认为导入有效但 WebPack 不认为有效?

为啥 Range 有效,但 Cells 无效?