map <int,int>默认值


Answers:


122

使用[]运算符访问地图后,如果键不存在,则会添加该键。将调用int类型的默认初始化程序-因此它将获得0值。


据我所知,未初始化的原语int的初始值是不确定的-可以是0,也可以是-99765521。是否曾经有未初始化int为类变量的代码,并且这些古怪的值之一出现在您的程序中?就是说,我对此进行了测试,并且似乎可行。 #include <stdio.h> #include <map> using namespace std; int main() { map<int,int> m ; for( int i = 0 ; i < 100 ; i++ ) m[i]++ ; for( const pair<int,int>& p : m ) printf( "m[%d] => %d\n", p.first, p.second ) ; }
bobobobo

29
它的工作方式与您想象的不同。int x; 使x获得一个不确定的值int x = int(); x再次获得0类foo {int x; foo():x(){}}; 富 此处的fx将为零
rep_movsd 2013年

@bobobobo:看看我的答案。初始化比这更复杂,并且取决于上下文具有多种“操作模式”。
Lightness Races in Orbit

我认为所有容器中的值都是在堆中创建的,并且堆中的值将使用适当的值进行初始化。在这种情况下,为0。对吗?
r0ng

1
在C ++中,堆和栈内存未初始化-一个对象由其默认构造函数初始化-该语言具有原始类型的默认构造函数,当您以正确的方式调用它们时,会将它们初始化为0请参阅我的早期评论
rep_movsd

40

是的,假设是安全的。

这样operator[]指定了地图:([map.access])

效果:如果x在地图中没有等效的键,则将其插入value_type(std::move(x), T())到地图中。
返回:向A参照mapped_type对应于x*this

T()对除([expr.type.conv] / 2)以外的所有都使用值初始化,而对基元使用值初始化会导致零初始化([dcl.init] / 7)Tvoid

因此,表达式的计算结果是对值为零([dcl.init] / 5)的对象的引用

operator++然后,该调用将该对象增加为1,并求值为1。

(所有参考文献均为C ++ 11。)


2
不知道为什么您的答案被否决是因为您是正确的。这正是规范所说的(我自己检查了一下)。
汉斯·德·鲁特

9

是的,默认值将是该类型的默认值。如果需要另一个默认值,则可以创建一个行为类似于int但具有不同默认构造函数的类。


6

Rep_Movsd的答案​​过于简单,可能导致许多极端危险的误解。C ++中的原始数据类型没有初始化程序。路易斯·布兰迪(Louis Brandy)进行了精彩的演讲,他讨论了Facebook上的许多常见C ++错误,并且误解了std :: map <> []的工作方式是他所讨论的错误之一,尽管他没有这样做,但这是一个很好的资源。详细介绍std :: map <> []的实际工作方式。

通常,像所有原始类型一样,int不会被初始化且未定义。话虽这么说,当与std :: map <> []一起使用时,int通过称为值初始化的过程将默认值设置为零。值初始化通常是一个与结构实际一起使用的过程。例如,

struct Struct {
Struct() : memberVariable() {}
       int memberVariable;
};

始终会将int初始化为零。如果成员变量是其他原始类型,则它们还将具有特定的初始化值。例如,通过像这样的值初始化来初始化以下类型:

bool = false
float = 0.0f
enum =(枚举类型)0
指针=空指针
指向成员的指针=空成员指针

使用未显式初始化的数据时,请格外小心。最后一件事,请考虑以下代码

map<string, int> myMap;
cout << myMap["Foo"];

此代码不仅将始终将整数初始化为0,而且还将0插入到映射中。只是为了快速回顾一下,如果未初始化原始数据类型,则未定义它们,但是在某些情况下(例如,使用struct或map值初始化)会使用特定值初始化原始数据。


2
“ C ++中的原始数据类型没有初始化程序”这被过度简化,并且可能导致危险的误解。“未初始化”不是。不是。这称为默认初始化,但是结果是不确定的值(C ++ 11 8.5 / 11)。“是不确定的”号。不确定。“结构” C ++没有结构。“值初始化”正确。关键是使用了不同的初始化类型。此外,您的散文中还包含一些逗号。
轻轨赛于

默认情况下,原始数据类型未初始化为任何值。他们没有默认构造。在某些情况下,它们确实具有价值建构。您试图在未定义和不确定的行为之间进行区分是荒谬的。根据C ++ 11标准,未定义的行为定义为:“ ...非便携式或错误程序构造或错误数据,对此本国际标准不施加任何要求”,实质上意味着发生逻辑或状态错误,并且结果未知。我从没说过结构来自C ++。
雷切尔·凯西

“您试图在未定义和不确定的行为之间做出区分是荒谬的。” 我没有区别,标准做了。如果您认为这很荒谬,那么您当然可以在ISO工作组邮件列表中提出反对意见。
轨道轻度比赛'18年

“我从未说过结构来自C ++。” 如果您已经知道这一点,那么为什么要讨论有关C ++问题的结构?现在荒谬了!
轨道轻度比赛'18年

1
不可以。无法在C ++中创建结构。仅可以使用Inheritedstruct关键字创建一个类。您显示的代码包含一个。C ++没有结构。进一步阅读:stackoverflow.com/a/36917400/560648 stackoverflow.com/a/34108140/560648
轨道轻度比赛
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.