C++ 常量键和非常量键的区别是什么?
以下两行之间有什么区别C++ 常量键和非常量键的区别是什么?,c++,key,language-lawyer,key-value,stdmap,C++,Key,Language Lawyer,Key Value,Stdmap,以下两行之间有什么区别 map<int, float> map_data; map<const int, float> map_data; map\u数据; 地图数据; 已经是常量,因此在这种情况下写入常量是多余的。输入元素后,其键无法更改 编辑: 如评论中所述,这两行之间存在差异。例如,如果您编写的函数接受map,则无法传递给它map,因为它们是不同的类型 但是请注意,尽管它们是不同的类型,但它们的行为是相同的,因为映射中的键是常量 因此,总而言之。。唯一的区别是,
map<int, float> map_data;
map<const int, float> map_data;
map\u数据;
地图数据;
已经是常量
,因此在这种情况下写入常量是多余的。输入元素后,其键
无法更改
编辑:
如评论中所述,这两行之间存在差异。例如,如果您编写的函数接受map
,则无法传递给它map
,因为它们是不同的类型
但是请注意,尽管它们是不同的类型,但它们的行为是相同的,因为映射中的键是常量
因此,总而言之。。唯一的区别是,它们是两种不同的类型,您不应该关心其他任何事情。const
一旦设置就不能更改。是的,根据文档和其他答案,您应该记住,键
已经是常量
链接:
链接:
int
和const int
是两种不同的类型
std::map
和std::map
同样是不同的类型
std::map
和std::map
之间的区别在某种程度上类似于,比如说,std::map
和std::map
之间的区别每种类型都有一个新的地图类型。
在非const
情况下,内部密钥类型仍然是非const
int
:
std::map<const int, float>::key_type => const int
std::map<int, float>::key_type => int
因此,如果您的实现允许的话,在所有重要的方面,您可能都看不到差异
但情况并非总是如此:标准正式要求您的密钥类型是可复制和可移动的,并且;在这些实现中,尝试使用常量键根本不起作用。常量指的是一个常量,一旦定义,就无法更改它。。。非常量键可能会发生更改。。。或者甚至不能更改,只是const(一旦定义)中保证“不更改”,而“更改”可能会也可能不会发生在非const内容中。区别在于第二个变量将映射的键类型设置为const int
。从“可修改性”的角度来看,这是多余的,因为贴图已经将其键存储为const
对象
但是,这也可能导致这两个贴图的行为出现意外和不明显的差异。在C++中,为类型<代码> T 编写的模板特化与类型<代码> > const t< /COD>不同。这意味着上述两个版本的地图最终可能会使用不同“卫星”模板的不同专门化,这取决于密钥类型。一个例子是键比较谓词。第一个将使用std::less
,而第二个将使用std::less
。通过利用这种差异,您可以轻松地使这些贴图按不同顺序对其元素进行排序
像这样的问题在新的C++11容器中更加明显,比如std::unordered_map
std::unordered_map
甚至不会编译,因为它将尝试使用std::hash
专门化对键进行散列。这种专门化在标准库中不存在。虽然应用程序的行为通常是相同的,但它会对您可能使用的某些编译器产生影响。首先,让我来到本页的更具体的例子是:
明确指定映射为map
使用gnu工具包成功构建
但是,它使Studio12 Solaris x86版本崩溃
map
在两者上都成功构建。应用程序的行为保持不变。如果键是指针,则常量键可能会有所帮助。使用const键不会让您在访问密钥时修改尖对象,请考虑如下:
#include <map>
#include <string>
int glob = 10;
int main() {
std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
std::map<int*, std::string> keyMap { { &glob, "bar" } };
for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR
return 0;
}
#包括
#包括
int glob=10;
int main(){
std::map constKeyMap{{&glob,“foo”};
映射键映射{{&glob,“bar”};
for(const auto&kv:keyMap){*(kv.first)=20;};//glob=20
for(const auto&kv:constKeyMap){*(kv.first)=20;};//编译错误
返回0;
}
这(完全)不正确。std::map
的接口将密钥类型公开为const
,但这并不意味着这两个模板实例化与此答案可能暗示的相同std::map
和std::map
是正确的。@jrok是正确的,而这个答案不是正确的。在前一种情况下,key\u type
实际上仍然是int
。@johnmac2332:让这一课讲得那么快吧!=太好了,还有投票正确。没有人是完美的,我们都会犯错,并互相学习。我们来这里学习和帮助:)@LightnessRacesinOrbit好的,是的!我同意你的看法。顺便说一句,你的回答很好。是的,一个人应该花时间发布和接受答案。我自己大部分时间都试图从基本答案和长篇大论的帖子中解释(当然是延迟和低投票率的帖子)。不管怎么说,我祝贺Maroun的10公里RP。Maroun发布了许多好的答案,我发现他是一个有价值的投稿人。对不起,我本来应该写信的——不能。Mods已经做了编辑-ThanksQuestion很熟悉“崩溃”是以什么方式发生的?@LightnessRacesinOrbit它抱怨std::map::insert
有多个声明。是的,正如我上面所说的:这对编译器有影响。通常当我们说“崩溃”时,我们指的是进程意外和不正常的运行时终止。编译器崩溃很少见,但确实会发生(特别是在新的语言功能中),而且本质上非常严重(随着构建结果的变化)。它会使我的构建崩溃,而不是应用程序崩溃。我是否误用了术语?当键类型为常量int*
时,指针本身不是常量,而是指向的int
为常量。因此差异为la
#include <map>
#include <string>
int glob = 10;
int main() {
std::map<const int*, std::string> constKeyMap { { &glob, "foo"} };
std::map<int*, std::string> keyMap { { &glob, "bar" } };
for(const auto& kv : keyMap) { *(kv.first) = 20; }; // glob = 20
for(const auto& kv : constKeyMap) { *(kv.first) = 20; }; // COMPILE ERROR
return 0;
}