c++26新功能—未初始化读取

一、什么是未初始化读取

Erroneous behaviour for uninitialized reads,未初始化读取。在传统的C++中,UB行为是一种非常笼统的叫法,一切不属于正常操作的行为都可以算是未定义。过于宽泛的定义往往会出现一个问题,就是出现问题后无法准确的定位到出问题的原因上。UB行为处理的简单是简单了,但不符合可控的安全原则。
Erroneous behaviour for uninitialized reads,就可以认为是对这种UB行为中的一种具体情况的说明。从这一点来看,这种发展的方向也符合所有语言,包括C++语言发展的整体方向的。所以在C++26中,将这种未初始化读取定义为错误,这样可以更明确的区分行为的最终确定性。

二、未初始化值

在以前的C++开发中,反复强调要对变量进行初始化。特别是栈上的变量,如果没有明确的初始化,在操作时,很可能产生UB行为。UB行为可能是正常的运行,也可能是不可思议的运行,也有可能是引起程序的崩溃…。毕竟对C++这类强类型语言来说,对程序运行的整体流程希望是全链路可明确、安全和异常可控的过程。但实际上开发者往往水平各有高低,写出的代码也是各有千秋,没办法,这样的结果就是上面的想法是理想的,但现实是过于丰满的。所以明确异常或错误的的行为,是一种非常必要的情况。看下面的例子:

void test(){
    int data;
    std::cout<<"data value is:"<<data<<std::endl;
}

对于大多数的程序员,都明白上面的例子中,data的值就是一种不确定的值。它也可以称为EB,Erroneous Behaviour。而新的C++标准就是为了让错误和异常变得更具有确定的原因说明,降低模糊性。C++26正是顺应了这一种趋势。当然,这种初始化中有很多种类,包括零初始化、强制初始化、默认初始化以及值初始化等都相应的进行了界定。这些就不再介绍,等标准最终发布后,大家直接看相关的内容即可。
当然,为了实现安全的操作行为,新标准也需要对未初始化的变量进行更新的定义,即“Default-initialization of an automatic-storage object initializes the object with a fixed value defined by the implementation; however, reading that value is a conceptual error”。换句话说,就是读取某些默认初始化也划到错误的概念中去,并希望标准能提供支持发现这种问题的机制。当然,为了向前兼容,也可以允许其忽略这种问题并视为这种行为的有效性或支持退出并恢复这种行为的机制。
需要说明的说,这次定义是一次谨慎的探索,只对单个的变量行为有效,而不支持一些多值等的使用。更具体的需要等待标准的最终发布。比如下面的例子:

void f() {
            char data[] = {'s', 'e', 'c', 'r', 'e', 't'};   // automatic variable
            ::new (static_cast<void*>(data)) char;          // default-initialization
          }

三、退出机制

在上面提到了有些情况可能就是不需要初始化,那么可以采用两种机制,一种是明确使用一种说明符,比如noinit;另外一种就是采用属性机制,如下面的代码:

int x = noinit;             //第一种
int x [[indeterminate]];    //第二种 

当然,还是那句话,最终还是要根据标准的最终情况为准。

四、总结

新标准的推出就是为了让C++语言整体的安全性和可控性实现进一步的确定性。人类对未知的和不可控的东西有着天然的畏惧,而且,确实也如此,不确定性往往引起不可知的问题。对于编程这种辅助人类的工具而言,不确定性是不受欢迎的。但话还得说回来,饭要一口口的吃,事要一件件的办。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值