与向量一起使用时,C ++ unordered_map失败

时间:2012-05-01 22:04:40

标签: c++ qt vector c++11 unordered-map

背景:我是从Java世界来的,我是C ++或Qt的新手。

为了使用unordered_map,我编写了以下简单程序:

#include <QtCore/QCoreApplication>
#include <QtCore>
#include <iostream>
#include <stdio.h>
#include <string>
#include <unordered_map>

using std::string;
using std::cout;
using std::endl;
typedef std::vector<float> floatVector;

int main(int argc, char *argv[]) {
    QCoreApplication a(argc, argv);

    floatVector c(10);
    floatVector b(10);

    for (int i = 0; i < 10; i++) {
        c[i] = i + 1;
        b[i] = i * 2;
    }

    std::unordered_map<floatVector, int> map;

    map[b] = 135;
    map[c] = 40;
    map[c] = 32;

    std::cout << "b -> " << map[b] << std::endl;
    std::cout << "c -> " << map[c] << std::endl;
    std::cout << "Contains? -> " << map.size() << std::endl;

    return a.exec();
}

不幸的是,我遇到了下面的错误,这个错误并不令人鼓舞。甚至没有行号。

  

: - 1:错误:collect2:ld返回1退出状态

对问题的根源有什么看法?

提前致谢。

2 个答案:

答案 0 :(得分:26)

§23.2.5,第3段说:

  

每个无序关联容器由Key参数化,由符合Hash要求(17.6.3.4)的函数对象类型Hash参数化,并充当类型{{1的参数值的哈希函数并且由二元谓词Key引起类型Pred的值的等价关系。

Key用作vector<float>并且不提供显式哈希和等价谓词类型意味着将使用默认的Keystd::hash<vector<float>>

等价关系的std::equal_to<vector<float>>很好,因为向量有一个运算符std::equal_to,这就是==使用的。

然而,没有std::equal_to专门化,这可能是你没有告诉我们的链接器错误。您需要提供自己的哈希才能实现此目的。

编写此类哈希的简单方法是使用boost::hash_range

std::hash<vector<float>>

然后你可以使用:

template <typename Container> // we can make this generic for any container [1]
struct container_hash {
    std::size_t operator()(Container const& c) const {
        return boost::hash_range(c.begin(), c.end());
    }
};

当然,如果你需要在地图中使用不同的等式语义,你需要适当地定义哈希和等价关系。


<子> 1。但是,请避免使用散列无序容器,因为不同的顺序会产生不同的散列,并且无法保证无序容器中的顺序。

答案 1 :(得分:3)

我发现R. Martinho Fernandes的答案不适合竞争性编程,因为大多数情况下,您必须使用提供的IDE,并且不能使用boost之类的外部库。如果您想充分利用STL,可以使用以下方法。

如上所述,您只需要编写一个哈希函数。而且它应该专门用于存储在向量中的数据类型。以下哈希函数假定使用int类型的数据:

struct VectorHasher {
    int operator()(const vector<int> &V) const {
        int hash=0;
        for(int i=0;i<V.size();i++) {
            hash+=V[i]; // Can be anything
        }
        return hash;
    }
};

请注意,您可以使用任何类型的操作来生成哈希。您只需要有创造力,以使冲突最小化。例如,hash^=V[i]hash|=V[i]hash+=V[i]*V[i]甚至hash+=(V[i]<<i)*(V[i]<<i)*(V[i]<<i)都是有效的,直到您的哈希不会溢出为止。

最后要在您的unordered_map中使用此哈希函数,请按以下步骤对其进行初始化:

unordered_map<vector<int>,bool,VectorHasher> hashMap;