在基于 std::map 构建容器时,我遇到了意外行为:检索不存在键的值不会提供使用默认构造函数构造的新对象。
我在这里缺少什么?
简化的测试用例程序:
#include <cstdio>
#include <algorithm>
#include <map>
#include <string>
static std::string to_lower(const std::string& str)
{
std::string lower_label;
std::transform(str.begin(), str.end(), lower_label.begin(), ::tolower);
return lower_label;
}
class Int {
public:
Int () : i(0) { }
Int (int _i) : i(_i) { }
int val() const { return i; }
private:
int i;
};
std::map<std::string, Int> ints;
Int GetInt(const std::string& label)
{
std::string lower_label = to_lower(label);
return ints[lower_label];
}
void AddInt(Int image, const std::string& label)
{
std::string lower_label = to_lower(label);
ints[lower_label] = image;
}
int main()
{
Int k;
printf ("default Int: %d\n", k.val());
AddInt(Int(5), "I5");
Int i = GetInt("i5");
printf ("existing Int: %d\n", i.val());
Int j = GetInt("LaLa");
printf ("non-existing Int: %d\n", j.val()); // expecting 0
return 0;
}
输出:
default Int: 0
existing Int: 5
non-existing Int: 5
最佳答案
您的转换
写入空字符串,因此程序具有未定义的行为。
实际情况是,当您返回时,lower_label
的长度仍然为零,因此每次调用 to_lower
时,您都会得到相同的键:一个空字符串。这意味着您的 map 有一个条目,并且每次调用 GetInt
都会返回相同的条目。
但是由于您有未定义的行为,所以您很幸运它不会崩溃或删除您的磁盘。
在尝试写入之前,您需要使用 back_insert_iterator
或正确设置字符串大小。
或者:
std::string lower_label;
std::transform(str.begin(), str.end(), std::back_inserter(lower_label), ::tolower);
或者:
std::string lower_label;
lower_label.resize(str.size());
std::transform(str.begin(), str.end(), lower_label.begin(), ::tolower);
关于c++ - std::map 中不存在的项上的运算符[]的返回值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26120046/