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;
}