【问题标题】:Error in Stroustrup's The C++ Programming Language?Stroustrup 的 C++ 编程语言中的错误?
【发布时间】:2013-07-04 20:14:11
【问题描述】:

Stroustrup 的C++ 编程语言(此处为第 4 版)第 6.3.5.1 节的最后一句是:

如果数组或结构被初始化,则默认初始化数组或类的成员。

但是,this test 显示默认初始化对象的 未初始化 成员(我也尝试使用 g++4.7 -std=c++11

#include <iostream>

struct Foo
{
    int i;

    Foo();
};

Foo::Foo() {}

int main()
{
    Foo f;
    std::cout << "f.i: " << f.i << std::endl;

    return 0;
}

我一定是遗漏了什么,但有什么解释不意味着 Stroustrup 的断言中有错误吗?


编辑:在回答之后,我了解到 default initialized 的概念应该在文本的其他部分包含所谓的 uninitialized 内容(例如,在 §17.3. 1)。这对我来说听起来很不清楚。实际上,使用 未初始化 来表示“未明确用户初始化”(如其中的情况)之外的任何内容是矛盾的:有些东西是默认初始化但未初始化。除非人们放弃 X 和 un-X 分类相反的、排他的事物集的自然语言证据......

此外,同一节(第 6.3.5.1 节)中的前一句为

局部变量 [...] 默认情况下不会初始化,除非它们是具有默认构造函数的用户定义类型 [...]

这里的矛盾再次明显。接受第一个和后一个语句为真意味着有变量(即局部变量)同时默认初始化默认未初始化

恕我直言,这充其量只是用自然语言来描述事物的一种非常不清楚的用法。

【问题讨论】:

  • 我认为是:“默认初始化”可以“初始化为未定义的值”。它初始化,可安全写入,但未定义读取。但是,是的,措辞令人困惑,而且确实自相矛盾。

标签: c++ default-constructor initialization built-in-types


【解决方案1】:

根据第 8.5/7 节:

默认初始化 T 类型的对象意味着:
— 如果 T 是(可能是 cv 限定的)类类型(第 9 条),则调用 T 的默认构造函数(如果 T 没有可访问的默认构造函数,则初始化是非良构的);
— 如果 T 是数组类型,则每个元素都是默认初始化的;
— 否则,不执行初始化。

int 位于最后一点,因此未初始化。如果您的成员具有 std::string 类型,它将调用 std::string 的默认构造函数,并且您将有一个空字符串。

【讨论】:

  • 我认为这充其量是不清楚的。从前面的文本中,您将理解默认初始化 int 的值为 0(例如,全局 int 变量就是这种情况)。事实上,上一页读到“局部变量 [...] 默认情况下不会初始化,除非它们是具有默认构造函数的用户定义类型”。因此,这将是一个默认初始化的变量(根据您发布的定义),但默认情况下不会被初始化......对我来说听起来不太连贯
  • @ricab,该标准定义了默认初始化、值初始化和零初始化。未初始化不是这些类别之一。对于您的全局变量注释,它们是零初始化的(第 3.6.2/2 节),这对于 int(基本上是所有东西)意味着 0。值初始化 int 也会给您 0。但是,默认 -初始化它不会,它会使其未初始化。当您声明一个没有任何初始化程序的普通本地 int 时,这是默认要做的事情。 int不是用户自定义类型,所以默认没有初始化。
  • @ricab,默认初始化会使事物未初始化这一事实听起来可能很奇怪,但它确实使分类变得更容易。
  • @chris 知道了,您的回答连同您的第一条评论回答了原始问题。尽管如此,这听起来像是我之前引用的错误陈述:“局部变量 [...] 默认情况下不会初始化,除非 [...]”。接受这两个(半页分隔)语句为真意味着存在默认初始化默认未初始化的变量。这确实不是我所期望的,我仍然认为它不清楚。
  • @chris,未初始化不是标准中定义的类别之一,但它是书中使用的概念(它甚至在最后被索引)。因此,我认为书中存在矛盾(标准中没有说)。请参阅我的编辑以获取更详细的推理
猜你喜欢
  • 2018-01-23
  • 1970-01-01
  • 2016-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多