【问题标题】:Issues with unordered_mapunordered_map 的问题
【发布时间】:2013-12-17 11:38:20
【问题描述】:

我正在尝试实现各种用于学习目的的数据结构和算法。

目前我正在尝试实现 Graph 类模板,但在尝试使用 STL unordered_map(以及将来的 consequently priority_queue)时遇到了问题。

目前发生的情况基本上是,由于某种原因,在尝试初始化图中的顶点映射时,模板类型不匹配。据我了解,由于我只打算使用本机 C++ 类型的键类型,只要我的值类型是指针,除了自定义顶点类的复制构造函数之外,我不需要做任何额外的工作。默认的比较器/哈希器就足够了。但事实并非如此,我收到的错误有点难以理解。

错误:

Error   1   error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::unordered_map<T,graph<T>::vertex *,std::hash<int>,std::equal_to<_Kty>,std::allocator<std::pair<const _Kty,_Ty>>>' (or there is no acceptable conversion)

代码:

#include "stdafx.h"
#include <iostream>
#include <vector>
#include <unordered_map>
#include <numeric>
#include <functional>

using namespace std;
class vertex;
template <class T>
class graph {
public:

graph() { verts = unordered_map<T, vertex*>(); }
~graph() {
    for each(auto v in verts)
        delete(v);
    delete(verts); 
}
private:
unordered_map<T, vertex*> verts;

// --- Inner Classes ---

struct path {
    vertex *dest;
    double cost;

    path(vertex *d = nullptr, double c = 0.0) : dest(d) : cost(c) {}

    inline int compare(const path& p) {
        auto other = p.cost;

        return cost < other ? -1 :
            cost > other ? 1 : 0;
    }
};

struct edge {
    vertex *dest;
    double cost;

    edge(vertex *d = nullptr, double c = 0.0) : dest(d) : cost(c) {}
};

class vertex {
public:
    // Vertex relationships
    T name;
    vector<edge>* adj;

    // Path Finding Information
    double distance;
    vertex *prev;
    int scratch;

    void reset_path_finding() {
        distance = double.infinity();
        prev = nullptr;
        scratch = 0;
    }

    vertex(T name = default(T)) : name(name) : adj(new vector<edge>) : 
        distance(double.infinity()) : prev(nullptr) : scratch(0) {}
    vertex(const vertex& v) {
        name = v.name;
        adj = v.adj;
        distance = v.distance;
        prev = v.prev;
        scratch = v.scratch;
    }
    ~vertex() { delete(adj); }
private:
};
};

int main()
{
graph<int> myGraph = graph<int>();

cout << "Press any key to continue..." << endl;
int x;
cin >> x;
return 0;
}

【问题讨论】:

  • 你能指出错误所在的源代码吗?
  • 顺便说一句,当您在 main 函数中声明一个变量(类成员、本地或全局)时,如 main 函数中的本地 myGraphgraph 类中的 verts,您不需要不必按照您的方式进行初始化。只要声明就足够了。

标签: c++ class graph map


【解决方案1】:

第一个问题是你在声明它之前使用了嵌套类graph::vertex。由于您声明了class vertex outside graph,因此引起了进一步的混乱,因此编译器最初认为您指的是那个类。您可以在graph 的开头附近声明vertex

template <class T>
class graph {
    class vertex;
private:
    // and so on
};

还有其他几个语法错误,如果您查看错误消息所引用的行,这些错误应该很明显。基于范围的 for 循环的语法是

for (auto v : verts)  // not for each(auto v in verts)

这为您提供了键值对,因此要删除 vertex,您需要

delete v.second;

更好的是,将verts 更改为unordered_map&lt;T, vertex&gt;,包含对象而不是指针,它会自动管理所有内存 - 你根本不需要析构函数。

值初始化临时的语法是

T()  // not default(T)

构造函数的初始化列表中的子句用逗号分隔,而不是冒号:

path(vertex *d = nullptr, double c = 0.0) : dest(d) , cost(c) {}
                                                    ^ not :

具有无限值的double

std::numeric_limits<double>::infinity() // not double.infinity()

您需要在其中包含&lt;limits&gt;

verts 不需要在析构函数中删除,因为您不需要 new 它。它也不需要从构造函数中的默认构造临时分配,因为它只是默认构造的。

在某些地方,您通过不必要地使用指针和new 让自己的生活变得困难。尽量避免new,除非你真的需要它;并了解RAII,尤其是智能指针和容器的使用,以备不时之需。

【讨论】:

  • 哇,谢谢。我将废弃这段代码,明天用这个反馈再做一次。我已经有足够的时间试图让它工作了。但是当我尝试编译该类作为一个整体时,您指出的许多事情甚至都没有作为错误消息出现。 (MS C++)除非我强制它进入 main 作为一个小测试 sn-p 有时甚至没有。例如,每种语法的不正确编译和行为都符合预期。我正在这台新电脑上下载 clang,但由于我住在农村地区,所以下载需要一点时间。
  • @MorphingDragon:由于它是一个模板,除非实例化它们所在的函数或类,否则不会检测到很多错误 - 除非程序使用(通常)不会发生它。尝试通过一次添加少量功能来构建大型类,边写边写测试,这样就不会出现一大堆错误。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-04-04
  • 2013-10-30
  • 1970-01-01
  • 2010-12-15
  • 1970-01-01
  • 2016-04-09
  • 2011-04-27
相关资源
最近更新 更多