std::map 其中键是动态的或字符串文字
std::map where key's are dynamic or string literal
我在最后一天一直在处理这个问题,我仍然失去了以下代码的解决方案:
#include <stdio.h>
#include <iostream>
#include <map>
int main()
{
std::map<char *, char *> ourmap;
std::map<char *, char *>::iterator ourmap_it;
ourmap["hello"] = "world";
ourmap["hello"] = "earth";
char * key = new char[5];
key[0] = 'h';
key[1] = 'e';
key[2] = 'l';
key[3] = 'l';
key[4] = 'o';
char * key_other = new char[5];
key_other[0] = 'h';
key_other[1] = 'e';
key_other[2] = 'l';
key_other[3] = 'l';
key_other[4] = 'o';
ourmap[key] = "venus";
ourmap[key] = "mars";
ourmap[key_other] = "jupiter";
for (ourmap_it = ourmap.begin(); ourmap_it != ourmap.end(); ++ourmap_it)
{
printf("map[%s] %sn", ourmap_it->first, ourmap_it->second);
}
ourmap.clear();
delete key;
delete key_other;
return 0;
}
键没有被覆盖,如果在动态键上执行find
,也会有相同的行为。输出更详细地解释了
map[hello] earth
map[hello] mars
map[hello] jupiter
问题1
在const char *
与@key
和@key
与@key_other
的情况下,为什么map
不是find
使两个值相等?
问题2
我应该使用不同的容器吗?或者使用不同的代码(定义不同的变量)。
在上面的代码中使用动态键是没有意义的,但是我的实际代码需要动态键,如果键值是从文件中读取的,而不是在代码中定义的,因为我不知道给定文件中键的大小,所以它必须是动态的。问题是,虽然我可以设置键,但我不能检索值。
我想创建一个我自己的发现,它在键上做一个strcmp
来找出等价,但这似乎很糟糕,所以在我绑定它之前只是咨询SO
。
任何帮助都太好了。由于
好的。一些想法。
- 你正在引起一些未定义的行为。您为一个字符串分配5个字节,并在该内存中放入
- 不能保证字符串字面值
"hello"
的两个实例具有相同的指针。标准将这个选项留给了实现。 - 我会用
std::string
代替char *
来解决你的大部分问题。
"hello"
,但是您没有足够的空间来null终止它。当你试图打印它时,会发生未定义的行为。让我们修复你代码中的一些bug,然后继续讨论:
int main() {
std::map<char const *, char const *> ourmap;
std::map<char const *, char const *>::iterator ourmap_it;
ourmap["hello"] = "world"; // (1)
ourmap["hello"] = "earth"; // (2)
char * key = new char[6];
key[0] = 'h';
key[1] = 'e';
key[2] = 'l';
key[3] = 'l';
key[4] = 'o';
key[5] = ' ';
char * key_other = new char[6];
key_other[0] = 'h';
key_other[1] = 'e';
key_other[2] = 'l';
key_other[3] = 'l';
key_other[4] = 'o';
key_other[5] = ' ';
ourmap[key] = "venus"; // (3)
ourmap[key] = "mars"; // (4)
ourmap[key_other] = "jupiter"; // (5)
for (ourmap_it = ourmap.begin(); ourmap_it != ourmap.end(); ++ourmap_it)
printf("map[%s] %sn", ourmap_it->first, ourmap_it->second);
}
我在代码中引用了4个位置。关于这些键我们知道些什么?
我们知道(2) != (3) != (5)
。但是我们能从(1) ?= (2)
推断出什么呢?通常情况下,(1)和(2)是不同的。然而,标准的允许(但不要求)编译器合并这两个字符串字面值以节省内存。也就是说,大多数编译器都这样做,特别是在一个编译单元内。
那么,让我们假设优化发生了
那么,让我们运行步骤1。我们的映射现在看起来像:
"hello" (1) => "world"
让我们运行第二步。
"hello" (1) => "earth"
注意,我们仍然只有一个元素在映射中,因为(1) == (2)
.
让我们运行第三步。
"hello" (1) => "earth"
"hello" (3) => "venus"
现在map中有两个元素,因为使用了两个不同的指针作为键。
我就讲到这里,但我想我已经讲得很清楚了。
或者,我们可以使用std::string。
int main() {
std::map<std::string, std::string> ourmap;
std::map<std::string, std::string>::iterator ourmap_it;
ourmap["hello"] = "world";
ourmap["hello"] = "earth";
char * key = new char[6];
key[0] = 'h';
key[1] = 'e';
key[2] = 'l';
key[3] = 'l';
key[4] = 'o';
key[5] = ' ';
char * key_other = new char[6];
key_other[0] = 'h';
key_other[1] = 'e';
key_other[2] = 'l';
key_other[3] = 'l';
key_other[4] = 'o';
key_other[5] = ' ';
ourmap[key] = "venus";
ourmap[key] = "mars";
ourmap[key_other] = "jupiter";
for (ourmap_it = ourmap.begin(); ourmap_it != ourmap.end(); ++ourmap_it)
printf("map[%s] %sn", ourmap_it->first.c_str(), ourmap_it->second.c_str());
}
这里的输出是:
map[hello] jupiter
这是因为std::string实现<
与char *
不同。比较字符串的内容。
再扩展一下最后一件事。下面是实现比较器的一个示例。
struct comparator {
bool operator()(const char * lhs, const char * rhs) const {
return strcmp(lhs, rhs) < 0;
}
};
int main() {
std::map<char const *, char const *, comparator> ourmap;
std::map<char const *, char const *, comparator>::iterator ourmap_it;
...
在本例中,就像std::string一样,我们将看到以下输出:
map[hello] jupiter
- std::向量与传递值的动态数组
- 在c++中用vector填充一个简单的动态数组
- C++中的动态铸造故障
- 如果C++类在类方法中具有动态分配,但没有构造函数/析构函数或任何非静态成员,那么它仍然是POD类型吗
- 内联映射初始化的动态atexit析构函数崩溃
- 使用动态分配的数组会导致代码分析发出虚假的C6386缓冲区溢出警告
- constexpr 函数中的非文字(通过 std::is_constant_evaluated)
- 我可以使用条件运算符初始化C风格的字符串文字吗
- 控制允许动态运行c++的并发操作数
- 如何将这个C++哈希表转换为动态扩展和收缩,而不是使用硬设置的最大值
- 在调用FreeLibrary后,释放动态链接到具有相同版本的CRT堆的DLL的内存
- 输出没有重复元素的动态数组(收缩数组)C++
- C++为线程工作动态地分割例程
- 正在插入动态数组
- 如何使用字符串文字作为宏参数
- 有没有办法从非C/C++文件中读取C++原始字符串文字的内容
- Pango/Cairo中的动态文字
- 动态分配字符串文字
- 如何在C++中使用字符串文字初始化字符的动态数组
- std::map 其中键是动态的或字符串文字