内置类型的 std::map 默认值

Posted

技术标签:

【中文标题】内置类型的 std::map 默认值【英文标题】:std::map default value for build-in type 【发布时间】:2011-05-30 06:23:19 【问题描述】:

最近,我对 std::map operator[] 函数感到困惑。 在 MSDN 库中,它说:“如果未找到参数键值,则将其与数据类型的默认值一起插入。” 我试图为这个问题寻找更准确的解释。例如这里: std::map default value 在这个页面中,Michael Anderson 说“默认值是由默认构造函数(零参数构造函数)构造的”。

现在我的任务是:“内置类型的默认值是多少?”。它与编译器有关吗?或者 c++ 标准委员会是否有针对这个问题的标准?

我在 Visual Studio 2008 上对“int”类型进行了测试,发现“int”类型的值是 0。

【问题讨论】:

我用“bool”类型做了一个测试。还有一些奇怪的东西:当我使用“bool b = new bool()”时,b 的值变成了 0;但是当我使用“bool *pb = new bool[10]; pb[0] = new bool();”然后 pb[0] 变成 1,即正值。哦,我在visual studio 2008上做了这个测试。 当你写pb[0] = new bool();时,new bool()是一个指针,而p[0]是一个布尔值。指针可以隐式转换为bool,如果指针为空指针,则返回结果false,否则返回true。因此,您观察到的真实值只是告诉您 new 没有返回空指针(当然,普通的 new 无论如何都不会返回)。另外,你泄露了分配。 【参考方案1】:

类类型对象的默认值是由类的默认构造函数设置的。对于内置类型,默认值为 0。

但请注意,未初始化的内置变量与已初始化为其默认值的变量之间存在差异。未初始化的内置函数可能会保存当时该变量的内存地址中的任何值。

int i;          // i has an arbitrary undefined value
int x = int();  // x is 0

【讨论】:

以上链接已过时。见这里:stroustrup.com/glossary.html。不知道它有什么帮助 不。对于内置类型,未定义默认值。内置类型的默认构造函数什么都不做。【参考方案2】:
 |expression:   | POD type T                               | non-POD type T
 ==================================================================================================
 | new T         | not initialized                          | default-initialized
 | new T()       | always default-initialized               | always default-initialized
 | new T(x)      | always initialized via a constructor     | always initialized via a constructor

据我所知,stl 使用 new T() 作为默认值,因此它将被默认初始化,以防 int 为 0。

【讨论】:

new T() 表示值初始化。值初始化不同于默认初始化。 new T() 暗示值初始化?使用new T()时值初始化和默认初始化有什么区别?【参考方案3】:

这是在标准中定义的,是的。在这种情况下,map 正在执行“默认初始化”。正如您所说,对于类类型,它调用无参数构造函数。

对于内置类型,在 '98 标准中,请参阅第 8.5 节“初始化程序”:

默认初始化 T 类型的对象意味着:

如果 T 是非 POD ... 如果 T 是数组类型 ... 否则,对象的存储是零初始化的

之前,

对 T 类型的对象进行零初始化存储意味着:

如果 T 是标量类型,则存储设置为转换为 T 的值 0(零)

标量类型有:

算术类型(整数、浮点) 枚举类型 指针类型 指向成员类型的指针

特别是,您看到的整数(初始化为零)的行为是由标准定义的,您可以依赖它。

【讨论】:

我刚刚在 C++11 标准中检查了这一点,它说的有些不同。它表示如果类型不是类或数组,则不执行初始化。所以我现在不确定标准容器中的默认值。 过时标准的引用具有误导性,因为默认情况下,许多 POD 实例没有默认初始化。即使在 C++98 中,POD 类型的默认设置也是根本不初始化它们。用 C++11 清理了术语(并且变得非常复杂)。只有值初始化才能可靠地进行零初始化。【参考方案4】:

C++11 标准仍然要求 std::map 对内置类型进行零初始化(就像以前的标准一样),但原因与 Luke Halliwell 的回答中的原因有些不同。特别是,“默认初始化”内置数据类型并不在 C++11 标准中意味着零初始化,而是意味着“什么都不做”。 std::map::operator[] 中实际发生的是“值初始化”。

尽管如此,新标准的最终结果与卢克的答案相同。这些值将被零初始化。以下是标准的相关部分:

第 23.4.4.3 节“地图元素访问”说

T& 运算符[](const key_type& x);

效果:如果映射中没有与 x 等效的键,则将 value_type(x, T()) 插入映射中。

...

表达式T()在第8.5节中描述

初始化器为空括号集的对象,即 (),应值初始化

X a();

并且这种“值初始化”在同一节中进行了描述

对 T 类型的对象进行值初始化意味着:

如果 T 是具有用户提供的构造函数 (12.1) 的(可能是 cv 限定的)类类型(第 9 条),则 T 的默认构造函数 被调用(如果 T 不可访问,则初始化格式错误 默认构造函数); 如果 T 是(可能是 cv 限定的)非联合类类型,没有用户提供的构造函数,则该对象为零初始化,如果 T 隐式声明的默认构造函数是不平凡的,即 构造函数被调用。 如果T是数组类型,那么每个元素都是值初始化的; 否则,对象被零初始化。

【讨论】:

以上是关于内置类型的 std::map 默认值的主要内容,如果未能解决你的问题,请参考以下文章

JS内置类型

默认构造函数是不是初始化内置类型?

为什么内置排序无法对向量的映射进行排序?

默认初始化

python-面向对象类的内置方法

python 继承机制(子类化内置类型)