C++ 未初始化和不确定之间的差异

C++ 未初始化和不确定之间的差异,c++,c++11,C++,C++11,我在看书 那里 讨论未初始化的和不确定的值。想知道两者的区别吗 我的理解是,未初始化意味着编译器将分配内存,而不是试图初始化对象不确定->访问此对象可能会导致未定义的行为。 如果我错了,请纠正我 还想知道默认初始化和值初始化之间的区别,我认为您的解释很接近,但并不完全正确 未初始化表示内存已保留,但未填充有意义的数据。一个简单的例子: int* ptr; 所有这些只是保留一段内存来包含指针,但由于还没有int,指针的值不会改变,而是包含指向无意义位置的随机垃圾地址 另一个例子: class M

我在看书

那里 讨论
未初始化的
不确定的
值。想知道两者的区别吗

我的理解是,
未初始化
意味着编译器将分配内存,而不是试图初始化对象<代码>不确定->访问此对象可能会导致未定义的行为。 如果我错了,请纠正我


还想知道
默认初始化
值初始化

之间的区别,我认为您的解释很接近,但并不完全正确

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

int* ptr;
所有这些只是保留一段内存来包含指针,但由于还没有int,指针的值不会改变,而是包含指向无意义位置的随机垃圾地址

另一个例子:

class MyClass
{
    int a;
    int b;

    MyClass() :
        a(b) //Oops
        b(5)
    { }
}
int b
用于
a
时尚未初始化,并且再次包含随机垃圾


不确定
状态是指对象已初始化,但(可能是因为不再打算使用它)您不知道其中包含什么

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

std::string a("text");
std::string b(std::move(a));
字符串a
现在可能只是一个空字符串。访问它不会导致未定义的行为,它的行为将类似于任何其他空字符串。除非你不确定它是空的

据你所知,它可能已经用对某个静态常量字符数组的引用替换了它的字符数组,并说
“这是一个不确定的对象,你为什么要访问我,别管我。”
。或者一些复杂的看似随机的字符序列,这是内部优化的结果。你不知道里面有什么,也不应该使用它。但当你这样做时,它不会给你未定义的行为。只是在未定义的数据上的无用行为


默认初始化
值初始化
不是您主要问题的一部分,您应该在单独的问题中询问这些问题(假设您在此网站上已经找不到答案)。

在 WhozCraig。评论中有一个关于读取值的讨论。问题是关于C99;C++11标准本身没有定义“不确定值”的含义(至少不是草案文件)。我将总结一些相关部分

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

3.17.2

1不确定值

未指定的值或陷阱表示形式

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

Steve Jessop评论C或C++中的一个未确定的或未初始化的值的影响。

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

我也从(CaldAdvutdial.com)中找到了关于C90、C99和C++('98和03)标准的评论。

75:

C++

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

579:

C90

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

C++

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


对于问题的最后一部分,在处有摘要,“未初始化”是属于对象的属性:已分配存储,但未存储任何值。“不确定”是属于某个值的属性:未指定该值具有该值类型的一组可能成员中的哪一个。在某些情况下,对未初始化的对象(读取对象的存储值)执行左值到右值转换的结果是一个不确定的值,而在其他情况下,这样做会导致未定义的行为。这个问题不特定于C++11,如果删除了该标记或添加了C++1y,我相信我可以提供一个比现在更好的答案。您希望将问题限制在C++11上有具体的原因吗?在您的
MyClass
示例中,
a
不仅仅包含随机垃圾。整件事都是未定义的行为。@juanchopanza:当然。但对于大多数存在的每个实现,您得到的特定未定义行为都是随机垃圾。@n如果您不接受这个答案,您是否发现它有问题?安腾有陷阱值。