简体   繁体   English

具有自定义键的C ++ unordered_map导致空值

[英]C++ unordered_map with custom key resulting in null values

I'm using a std::unordered_map with keys of Currency and values with a double of the currency price. 我正在使用带有Currency键的std::unordered_map和具有货币价格double的值。 Currency is a custom class that I made. Currency是我制作的自定义类。 Here is one version that I have tried: 这是我尝试过的一个版本:

#ifndef CURRENCY_H
#define CURRENCY_H

#include "Nameable.h"
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
#include <boost/functional/hash.hpp>
#include "BigDecimal.h"
#include <iostream>

/**
 * Represents a single currency. Can be used as keys in a map and as a general
 * identifier for determining what unit a value of money is.
 * @param name
 */
class Currency: public Nameable {
public:
    Currency(std::string name) throw(NameAlreadyTakenException);
    Currency(const Currency& orig);
    virtual ~Currency();
    virtual std::string getName();
    virtual void setName(std::string name) throw(NameAlreadyTakenException);
    inline bool operator==(const Currency& key) const {
        return this->id == key.id;
    }

    // A custom hasher that I tried using.
    struct currencyHasher
        {
        std::size_t operator()(const Currency& k) const
        {
            return boost::hash<boost::uuids::uuid>()(k.id);
        }
    };
    boost::uuids::uuid id;
private:

};
// A template specialization for Currency. 
namespace std {
    template <>
    struct hash<Currency> {
        std::size_t operator()(const Currency& k) const {
            cout<< boost::hash<boost::uuids::uuid>()(k.id)<<"\n";
            return boost::hash<boost::uuids::uuid>()(k.id);
        }
    };
}
#endif  /* CURRENCY_H */

And here is the implementation: 这是实现:

#include "Currency.h"

Currency::Currency(std::string name) throw(NameAlreadyTakenException) {
    this->setName(name);
    this->id = boost::uuids::random_generator()();
}

Currency::Currency(const Currency& orig) {

}

Currency::~Currency() {
}

std::string Currency::getName() {
    return this->name;
}

void Currency::setName(std::string name) throw(NameAlreadyTakenException) {
    this->name = name;
}

I tried making Currency key-compatible by implementing both suggestions given by the answer to: C++ unordered_map using a custom class type as the key . 我通过使用自定义类类型作为键来实现C ++ unordered_map答案给出的两个建议,从而使Currency键兼容。 As you can see I've overridden the operator== as well as providing a custom hasher as well as specialize the template. 如您所见,我已经覆盖了operator ==,并提供了自定义哈希器以及专门化模板。

Despite all of this, the keys seem to be losing the values. 尽管如此,这些键似乎正在丢失值。 By this I mean doubles, floats and ints get turned into 0 and string get turned into empty strings. 我的意思是说,双精度数,浮点数和整数都变成0,而字符串变成空字符串。 Of course, it causes other problems with anything else that I use as a value. 当然,它会导致其他问题,而我将其用作值。 For example: 例如:

Currency dollar("Dollar")
std::unordered_map<Currency,int,Currency::currencyHasher> currenMap;
currenMap[dollar]=1337;
std::cout<<currenMap[dollar]<<"\n";

The output of this in the console is 0. Utilizing the template specialization doesn't work either: 在控制台中,此命令的输出为0。使用模板专用化也不起作用:

std::unordered_map<Currency,int> currenMap;
currenMap[dollar]=1337;
std::cout<<currenMap[dollar]<<"\n";

produces a 0 as well... 也会产生一个0 ...

Could the fact that Currency is a subclass of Nameable be causing problems? CurrencyNameable的子类的Nameable会引起问题? I'm using the boost::uuid as the hash (utilizing boost::hash<boost::uuids::uuid> to convert the id into a size_t ) I'm not sure what I'm missing, I thank you for your help. 我使用boost :: uuid作为哈希值(利用boost::hash<boost::uuids::uuid>将id转换为size_t )我不确定我缺少什么,谢谢你的帮助。

The issue is with the copy constructor: 问题出在拷贝构造函数上:

Currency::Currency(const Currency& orig) {

}

When you copy a Currency , you get a default-constructed id . 复制Currency ,您会得到一个默认构造的id When you insert a Currency into the map, it gets copied, and that copy will have a different id than the original. 当您将Currency插入地图时,它会被复制,并且该副本将具有与原始ID不同的ID。 Thus this: 因此:

currenMap[dollar]=1337;

is effectively adding {Currency(), 1337} into the map. 有效地将{Currency(), 1337}到地图中。 So when you are looking up the one with whatever id gets created for dollar , it won't be there. 因此,当您查找具有为dollar创建的id的对象时,它就不会在那里。 It's not that the value gets "zeroed out"... it's that you get a default-constructed value back. 并不是说该值被“清零”了……而是您得到了默认构造的值。

Fixing your copy constructor should fix the problem. 修复副本构造函数应该可以解决该问题。

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

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