【问题标题】:Returning a value from a map matching the type of the return value从匹配返回值类型的映射中返回一个值
【发布时间】:2016-05-14 19:08:26
【问题描述】:

我收到以下错误

In file included from /Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:2:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/string:439:
In file included from /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/algorithm:628:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/memory:1673:31: error: no matching constructor for initialization of 'Vertex'
            ::new((void*)__p) _Up(_VSTD::forward<_Args>(__args)...);

这里是我的代码相关部分的删节版:

class Vertex {
 public:
    int label;
    vector<Vertex> adjacent_vertices;
    Vertex(const int l) : label(l) { }
    Vertex(const int l, vector<Vertex> adjacents) : label(l), adjacent_vertices(adjacents) { }
    Vertex(const Vertex& other_vertex) : label(other_vertex.label), adjacent_vertices(other_vertex.adjacent_vertices){ }
};
class Graph {
 public:
    unordered_map<int, Vertex> vertices;
    protected:
    Vertex getmake_vertex(const int v) {
        if (vertices.find(v) == vertices.end() ) {
            // not found, make new vertex
            vertices[v] = Vertex(v);
        }
        return vertices[v];
    };
};

我已经确认在所有其他注释掉的情况下运行它会产生编译器错误。有人可以向我解释为什么会发生这种情况以及如何解决吗? Here 是带有完整编译器输出的要点。

【问题讨论】:

    标签: c++ constructor compiler-errors


    【解决方案1】:

    当您说vertices[v] = Vertex(v); 时,它必须为键v(在赋值之前)创建一个Vertex,但Vertex 没有默认构造函数。

    你应该使用vertices.insert(make_pair(v, Vertex(v)))甚至vertices.emplace(v, Vertex(v))

    这也适用于return vertices[v];。即使你和我都知道在这个 return 语句被命中时 v 已经有了一个值,但编译器不会并且仍然必须生成代码来可能生成一个,这会导致错误。

    将其设置为return vertices.find(v)-&gt;second; 将修复该部分。无需检查并确保 find 值不是 end,因为如果它不存在,我们只是将其放入。

    【讨论】:

    • 该方法旨在创建顶点,如果它不存在,然后返回它。而且由于每个顶点都需要一个标签,我该如何创建一个默认构造函数?
    • 这确实是你的做法,以防你的班级没有默认 c'tor
    • 是的,没关系。你仍然把它放在你的 if (vertices.find(v)...) 块中
    • 我正在使用参数v 创建顶点,这是列出的第一个构造函数。
    • 用您的任一选项替换 vertices[v] = Vertex(v) 会导致编译器错误
    【解决方案2】:

    使用operator[] 要求您的情况下的mapped_type (Vertex) 是默认可构造的1,因为它插入了默认构造的1@987654327 @如果地图中不存在键。这是一个运行时决定,因此即使密钥确实存在,您仍然需要在编译时使用默认构造函数。

    在 C++17 中,使用 try_emplace:

    Vertex getmake_vertex(const int v) {
        return vertices.try_emplace(v, v).first->second;
    }
    

    否则,请使用insertemplace

    Vertex getmake_vertex(const int v) {
        return vertices.insert({v, v}).first->second;
    }
    

    (如果您创建 Vertex(int) 构造函数 explicit,您可能需要使用 Vertex(v),您可能应该这样做。)

    如果键已经在地图中,则这些都不会实际插入。三个都 返回一个pair&lt;iterator, bool&gt;,其中迭代器指向具有指定键的元素。


    1 不完全正确,但对我们的目的来说足够正确。

    【讨论】:

      【解决方案3】:

      如果我正确阅读了这部分错误消息,则它需要Vertex 的默认构造函数;尤其是这个:

      需要 2 个参数,但提供了 0 个

      /Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:14:5: note: candidate constructor not viable: requires single argument 'l', but no arguments were provided
          Vertex(const int l) : label(l) { }
          ^
      /Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:16:5: note: candidate constructor not viable: requires single argument 'other_vertex', but no arguments were provided
          Vertex(const Vertex& other_vertex) : label(other_vertex.label), adjacent_vertices(other_vertex.adjacent_vertices){ }
          ^
      /Users/james/ClionProjects/United States Computing Olympiad/graphs.cpp:15:5: note: candidate constructor not viable: requires 2 arguments, but 0 were provided
          Vertex(const int l, vector<Vertex> adjacents) : label(l), adjacent_vertices(adjacents) { }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-11
        • 2019-01-05
        • 2015-04-05
        相关资源
        最近更新 更多