简体   繁体   English

unordered_map的问题

[英]Issues with unordered_map

I'm trying to implement various data structures and algorithms for learning purposes. 我正在尝试实现各种数据结构和算法以用于学习目的。

At the moment I'm trying to implement a Graph class template but I'm having issues with trying to use STL unordered_map (and consequently priority_queue in the future). 目前,我正在尝试实现Graph类模板,但是在尝试使用STL unordered_map (以及将来使用consequently priority_queue )时遇到问题。

Basically what happens at the moment is, for some reason, the template types don't match up when trying to initialize the vertex map within the graph. 基本上,由于某种原因,当前发生的情况是,在尝试初始化图形中的顶点图时,模板类型不匹配。 From what I understand, since I only plan to use key types from the native C++ types, as long as my value type is a pointer I shouldn't need to do any extra work apart from a copy constructor for my custom vertex class. 据我了解,由于我只打算使用本机C ++类型的键类型,因此只要我的值类型是一个指针,我就不需要为自定义顶点类的副本构造函数做任何额外的工作。 The default comparer/hasher should suffice. 默认的比较器/哈希器就足够了。 But it doesn't and the error I'm receiving is kind of incomprehensible. 但事实并非如此,我收到的错误有点难以理解。

The error: 错误:

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)

The code: 编码:

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

The first problem is that you use the nested class graph::vertex before declaring it. 第一个问题是在声明之前使用嵌套的类graph::vertex Further confusion is caused because you've declared class vertex outside graph , so the compiler initially thinks you mean that class. 由于您已经 graph 之外声明了class vertex ,因此造成了进一步的混乱,因此编译器最初认为您是指该类。 You could declare vertex near the start of graph : 您可以在graph的起点附近声明vertex

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

There are several other syntax errors, which should be obvious if you look at the lines referred to by the error messages. 还有其他一些语法错误,如果查看错误消息所引用的行,这些错误应该很明显。 The syntax for a range-based for loop is 基于范围的for循环的语法是

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

This gives you key-value pairs, so to delete the vertex , you need 这将为您提供键值对,因此要删除vertex ,您需要

delete v.second;

Better still, change verts into unordered_map<T, vertex> , containing objects rather than pointers, and it will manage all its memory automatically - you won't need a destructor at all. 更好的是,将verts转换为unordered_map<T, vertex> ,它包含对象而不是指针,并且它将自动管理其所有内存-您根本不需要析构函数。

The syntax for a value-initialised temporary is 值初始化的临时语法为

T()  // not default(T)

Clauses in a constructor's initialiser list are separated by commas, not colons: 构造函数的初始化程序列表中的子句用逗号而不是冒号分隔:

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

A double with infinite value is 具有无限值的double

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

for which you need to in include <limits> . 您需要在其中包含<limits>

verts doesn't need deleting in the destructor, since you don't new it. verts不需要在析构函数中删除,因为您不需要new它。 Nor does it need assigning from a default-constructed temporary in the constructor, since it's just been default-constructed. 由于它只是默认构造的,因此也不需要从构造函数中的默认构造的临时对象进行赋值。

There are a few places where you are making life difficult for yourself through unnecessary use of pointers and new . 在某些地方,您会因不必要地使用指针和new而使自己的生活变得困难。 Try to avoid new except when you really need it; 除非真正需要,否则尽量避免使用new东西。 and learn about RAII , especially the use of smart pointers and containers, for when you do. 并在需要时了解RAII ,尤其是使用智能指针和容器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM