【问题标题】:Insert an `int` value into a `std::map`, which is supposed to store `std::string`将 `int` 值插入 `std::map`,它应该存储 `std::string`
【发布时间】:2013-12-15 23:50:45
【问题描述】:

我刚遇到以下情况:

std::map< int, std::string > mm;
mm[ 1 ] = 5;
std::cout << mm[1];
assert( mm.find( 1 ) != mm.end() );

这确实 NOT 打印任何内容,而 assert 确实 NOT 失败。

这似乎是一个错字,它一定是mm[ 1 ] = '5';。想通之后,我尝试了:

std::string s1( 5 );
std::string s2 = 5;

如果编译成功,则无。会发生什么?

【问题讨论】:

  • 如果有人建议一个更好的标题,我会很高兴。
  • 5 的问题是 char=0x05 不是可打印的。如果你写了一个更大的数字,你会得到一个可识别的字符被打印出来。
  • 为什么应该是mm[1] = '5'。既然你使用的是字符串,不应该是mm[1] = "5"吗?
  • @0x499602D2 - 在这种情况下是一样的。但是是的,也可以是"5"

标签: c++ string map int


【解决方案1】:

std::map::operator[] 首先创建一个类型为std::map::mapped_type 的元素,然后返回对它的引用。

所以,这里发生的情况如下:

  1. std::string 对象已创建并默认构造;
  2. 创建的对象被插入到std::map
  3. 返回对插入元素的引用
  4. 在这个对象上调用operator=

在这种情况下,std::string::operator= 被调用。

“魔法”来了——有一个重载的operator=,将char 作为参数。此外,该数字可以隐式转换为char。所以,实际上发生的是:

std::string s;
s = (char)5;

例如,这个:

mm[ 1 ] = 65; // ASCII for 'A'
mm[ 2 ] = 98; // ASCII for 'b'
std::cout << m[ 11 ] << mm[ 2 ];

将打印Ab

【讨论】:

  • 有些烦人的东西,可以用explicit C++11 关键字轻松解决...
  • @user2485710 - explicit 不是 C++11 关键字,它在此之前。它仅适用于构造函数。我们正在谈论operator= 和整数类型之间的隐式转换。我认为这无关紧要。除非explicit 有新的含义(扩展)。
  • 嗯,是的,即使是 auto 关键字,它在 C++11 中也不是什么新鲜事,但我是在“大声思考”,它并没有使用强类型系统C++ 必须提供,甚至在逻辑上也没有多大意义。我认为在这种情况下使用explicit 可能非常有用,并且在代码中几乎任何需要在两种类型之间进行隐式转换的地方;但你是对的,这仍然是不可能的。
  • @user2485710 我认为auto 的情况不同。此处不能使用explicit,因为intchar 或任何其他整数类型都没有构造函数。你实际上不能在任何地方明确表示。我不明白你对 auto 的看法——关于它现在的意思还是以前的意思?
  • auto 是 C++11 之前很久以前的一个保留关键字,这几乎就是我想说的,C++11 添加了类型推导机制,为 @ 赋予了新的含义987654345@ 但关键字本身并不新鲜。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-19
  • 1970-01-01
  • 2022-10-22
  • 1970-01-01
  • 2019-10-06
  • 1970-01-01
  • 2019-05-07
相关资源
最近更新 更多