std::map 未找到密钥,即使条目相同
std::map key not found even though the entries are identical
我正在学习 C++,我一直在为 std::map 和 std::string 编写包装程序,但我偶然发现了一个问题。每当我使用字符串作为键向地图添加某些内容时,一旦我尝试使用完全相同的键访问该项目,它就会说该键超出了地图的范围。这是我的代码(不相关的部分被遗漏):
ADictionary.h
#ifndef ADICTIONARY_H
#define ADICTIONARY_H
#include <map>
...
template<typename KEY, typename VALUE>
class ADictionary {
public:
...
VALUE operator [](KEY key) const {
return value.at(key);
}
void add(KEY key, VALUE value) {
this->value.insert(std::make_pair(key, value));
}
...
private:
std::map<KEY, VALUE> value;
};
#endif
AString.cpp
#include "AString.h"
AString::AString() {
value = "";
}
AString::AString(const char character) {
value = character;
}
AString::AString(const char * characters) {
value = characters;
}
AString::AString(std::string text) {
value = text;
}
...
AString::operator const char *() const {
return value.c_str();
}
AString::operator const std::string() const {
return value;
}
...
ABoolean AString::operator<(AString & text) const {
return getLength() < text.getLength();
}
ABoolean AString::operator>(AString & text) const {
return text < *this;
}
ABoolean AString::operator==(AString & text) const {
return value == text.value;
}
ABoolean AString::operator!=(AString & text) const {
return !(text == *this);
}
AString & AString::operator=(AString & text) {
value = text.value;
return *this;
}
...
The code which uses the above
ADictionary<AString, AString> test;
AString a = "a";
AString b = "b";
test.add(a, b);
std::cout << test[a]; // Error occurs here, according to the program "a" is not a key in the map
我希望有人能向我解释发生了什么问题。我试过用默认的 std::string 作为类型创建一个字典,它工作正常:
ADictionary<std::string, std::string> test;
std::string a = "a";
std::string b = "b";
test.add(a, b);
std::cout << test[a]; // No error this time
如我所说,我是 C++ 的新手,所以可能还有其他错误。如果是这样,请随时指出它们。
谢谢!
编辑:
AString.h
#ifndef ASTRING_H
#define ASTRING_H
#include <string>
#include "ABoolean.h"
#include "AInteger.h"
#include "AList.h"
class ABoolean;
class AInteger;
template<typename VALUE>
class AList;
class AString {
public:
AString();
AString(const char);
AString(const char *);
AString(std::string);
~AString();
operator const char *() const;
operator const std::string() const;
operator const AInteger() const;
ABoolean operator<(AString &) const;
ABoolean operator>(AString &) const;
ABoolean operator==(AString &) const;
ABoolean operator!=(AString &) const;
AString & operator=(AString &);
AString & operator+(AString &);
AString & operator+=(AString &);
void clear();
ABoolean contains(AString) const;
AInteger getIndex(AString) const;
AInteger getLength() const;
AList<AString> getSplit(AString) const;
AString getSubstring(AInteger, AInteger) const;
void removeRange(AInteger, AInteger);
void removeSubstring(AString);
void toLowercase();
void toUppercase();
private:
std::string value;
};
AString & operator+(const char, AString &);
AString & operator+(const char *, AString &);
#endif
您的字符串运算符似乎不正确。
std::map 默认使用小于运算符。当您为 AString 提供一个时,它所做的唯一一件事就是检查字符串的长度。如果两个字符串长度相等怎么办?
正确的做法是按字典顺序比较字符串中的字符。虽然有一个标准库函数可以执行此操作,但您可以在 class:
中使用 std::string 值的运算符 <
friend bool operator<(AString const& a, AString const& b)
{
return a.value < b.value;
}
编辑:您可能还希望删除转换运算符,或者至少使它们显式化,以防止意外和不需要的隐式转换。采用一个参数的构造函数(复制或移动构造函数除外)也应显式声明。
我正在学习 C++,我一直在为 std::map 和 std::string 编写包装程序,但我偶然发现了一个问题。每当我使用字符串作为键向地图添加某些内容时,一旦我尝试使用完全相同的键访问该项目,它就会说该键超出了地图的范围。这是我的代码(不相关的部分被遗漏):
ADictionary.h
#ifndef ADICTIONARY_H
#define ADICTIONARY_H
#include <map>
...
template<typename KEY, typename VALUE>
class ADictionary {
public:
...
VALUE operator [](KEY key) const {
return value.at(key);
}
void add(KEY key, VALUE value) {
this->value.insert(std::make_pair(key, value));
}
...
private:
std::map<KEY, VALUE> value;
};
#endif
AString.cpp
#include "AString.h"
AString::AString() {
value = "";
}
AString::AString(const char character) {
value = character;
}
AString::AString(const char * characters) {
value = characters;
}
AString::AString(std::string text) {
value = text;
}
...
AString::operator const char *() const {
return value.c_str();
}
AString::operator const std::string() const {
return value;
}
...
ABoolean AString::operator<(AString & text) const {
return getLength() < text.getLength();
}
ABoolean AString::operator>(AString & text) const {
return text < *this;
}
ABoolean AString::operator==(AString & text) const {
return value == text.value;
}
ABoolean AString::operator!=(AString & text) const {
return !(text == *this);
}
AString & AString::operator=(AString & text) {
value = text.value;
return *this;
}
...
The code which uses the above
ADictionary<AString, AString> test;
AString a = "a";
AString b = "b";
test.add(a, b);
std::cout << test[a]; // Error occurs here, according to the program "a" is not a key in the map
我希望有人能向我解释发生了什么问题。我试过用默认的 std::string 作为类型创建一个字典,它工作正常:
ADictionary<std::string, std::string> test;
std::string a = "a";
std::string b = "b";
test.add(a, b);
std::cout << test[a]; // No error this time
如我所说,我是 C++ 的新手,所以可能还有其他错误。如果是这样,请随时指出它们。
谢谢!
编辑:
AString.h
#ifndef ASTRING_H
#define ASTRING_H
#include <string>
#include "ABoolean.h"
#include "AInteger.h"
#include "AList.h"
class ABoolean;
class AInteger;
template<typename VALUE>
class AList;
class AString {
public:
AString();
AString(const char);
AString(const char *);
AString(std::string);
~AString();
operator const char *() const;
operator const std::string() const;
operator const AInteger() const;
ABoolean operator<(AString &) const;
ABoolean operator>(AString &) const;
ABoolean operator==(AString &) const;
ABoolean operator!=(AString &) const;
AString & operator=(AString &);
AString & operator+(AString &);
AString & operator+=(AString &);
void clear();
ABoolean contains(AString) const;
AInteger getIndex(AString) const;
AInteger getLength() const;
AList<AString> getSplit(AString) const;
AString getSubstring(AInteger, AInteger) const;
void removeRange(AInteger, AInteger);
void removeSubstring(AString);
void toLowercase();
void toUppercase();
private:
std::string value;
};
AString & operator+(const char, AString &);
AString & operator+(const char *, AString &);
#endif
您的字符串运算符似乎不正确。
std::map 默认使用小于运算符。当您为 AString 提供一个时,它所做的唯一一件事就是检查字符串的长度。如果两个字符串长度相等怎么办?
正确的做法是按字典顺序比较字符串中的字符。虽然有一个标准库函数可以执行此操作,但您可以在 class:
中使用 std::string 值的运算符 <friend bool operator<(AString const& a, AString const& b)
{
return a.value < b.value;
}
编辑:您可能还希望删除转换运算符,或者至少使它们显式化,以防止意外和不需要的隐式转换。采用一个参数的构造函数(复制或移动构造函数除外)也应显式声明。