未初始化和不确定的区别

Posted

技术标签:

【中文标题】未初始化和不确定的区别【英文标题】:Difference between uninitialized and indeterminate 【发布时间】:2014-05-23 13:01:12 【问题描述】:

我正在阅读Do the parentheses after the type name make a difference with new

那里有Michael Burr 谈论uninitializedindeterminate 值。想知道两者的区别。

我的理解是,uninitialized 的意思是,编译器将分配内存而不是尝试初始化对象。 indeterminate-> 访问该对象可能会导致未定义的行为。 如果我错了,请纠正我。

也想知道default-initializationvalue-initialization的区别。

【问题讨论】:

对于你问题的最后一部分,在en.cppreference.com/w/cpp/language/default_initialization和en.cppreference.com/w/cpp/language/value_initialization有总结 “未初始化”是属于对象的属性:已分配存储空间但没有存储值。 “indeterminate”是属于一个值的属性:它未指定该值具有该值类型的可能成员集合中的哪一个。在某些情况下,对未初始化对象执行左值到右值转换(读取对象的存储值)的结果是一个不确定的值,而在其他情况下,这样做会导致未定义的行为。 这个问题不是 C++11 特有的,如果该标签被删除或者如果 C++1y 被添加,我相信我可以提供比你现在拥有的更好的答案。您是否有特定原因希望将问题限制在 C++11 上? 【参考方案1】:

我认为你的解释很接近,但不是完全正确

uninitialized 表示内存已保留,但未填充有意义的数据。一个简单的例子:

int* ptr;

所有这一切都是保留一块内存来包含指针,但由于还没有 int,该指针的值不会改变并且包含一个随机垃圾地址到一个无意义的位置。

另一个例子:

class MyClass

    int a;
    int b;

    MyClass() :
        a(b) //Oops
        b(5)
     

int b 用于a 时尚未初始化,并且再次包含随机垃圾。


indeterminate 状态是对象已被初始化,但(可能是因为它不再打算使用)您不知道其中的内容。

它的行为是不可预测的,但不是无效的(当然,除非文档说它也是无效的)。例如:

std::string a("text");
std::string b(std::move(a));

string a 现在可能只是一个空字符串。访问它不会导致未定义的行为,它的行为与任何其他空字符串一样。除非你不确定它是空的。

就您所知,它可能已将其 char 数组替换为对某个静态 const char 数组的引用,例如 "this is an indeterminate object why are you accessing me leave me alone."。或者一些复杂的一系列看似随机的字符,这是内部优化的结果。你不知道里面有什么,也不应该使用它。但是当你这样做时,它不会给你未定义的行为。只是对未定义数据的无用行为。


default-initializationvalue-initialization 不是您的主要问题的一部分,您应该在单独的问题中询问这些问题(假设您已经在此网站上找不到答案)。

【讨论】:

在您的 MyClass 示例中,a 不仅包含随机垃圾。整个事情都是未定义的行为 @juanchopanza:当然。但是对于大多数存在的特定未定义行为的实现来说,你得到的是随机垃圾。 @Nishith 你不接受这个答案,你发现它有问题吗?【参考方案2】:

What is Indeterminate value? 有一个很好的答案 沃兹克雷格。 cmets 中有关于读取值的讨论。问题是关于 C99; C++11 标准本身并没有定义“不确定值”的含义(至少不是草案文档)。我会总结一些相关的部分。

问题本身在C99中有不确定值的定义:

3.17.2

1 个不确定的值

未指定的值或陷阱表示

链接的答案链接到另一个关于trap representation 的好问题以获取更多信息。

Steve Jessop 研究在 C 或 C++ 中读取不确定或未初始化值的影响。

int 是否有任何陷阱表示是实现定义的。如果没有(而且我从未真正使用过具有 int 陷阱值的实现),那么读取不确定值就不是未定义的行为:您知道它不是陷阱值,因此它是有效值int 类型的,只是未指定哪一个。相比之下,在 C++ 中,读取任何未初始化的值都是显式 UB。在 C 和 C++ 中,读取陷阱表示都是 UB

我还从The New C Standard(coding-guidelines.com) 中找到了这些符合 C90、C99 和 C++('98 和 '03)标准的内容。

75:

C++

对象可能具有不确定的值。但是,该标准并未明确说明该值的属性。

579:

C90

C90 标准规定读取未初始化的对象是未定义的行为。但是,它没有为任何其他表示指定未定义的行为。

C++

C++ 标准没有明确指定任何此类行为。

【讨论】:

安腾有陷阱值。

以上是关于未初始化和不确定的区别的主要内容,如果未能解决你的问题,请参考以下文章

赋值为0或null,和不赋值的区别

在keil中初始化时如何定义一个全局变量,并且赋初值为0xff

VB中 randomize 是用来干啥的 +他和不+他有啥区别 请举例说明

Var与Dynamic的区别

Flutter Firebase中的核心/未初始化

C编译器如何处理使用未初始化的变量?