C++ 在C+中不指定对象的左值+;14

C++ 在C+中不指定对象的左值+;14,c++,language-lawyer,c++14,lvalue,C++,Language Lawyer,C++14,Lvalue,我在这里使用N3936作为参考(如果C++14中的任何文本不同,请更正此问题) 根据3.10左值和右值,我们有: 每个表达式都恰好属于该分类法中的一个基本分类:lvalue、xvalue或prvalue 然而,左值的定义如下: 左值[…]表示函数或对象 在4.1左值到右值转换中,文本出现: […]在所有其他情况下,转换结果根据以下规则确定: [...] 否则,glvalue指示的对象中包含的值就是prvalue结果 我的问题是:如果左值不指定对象,代码中会发生什么?有两个典型的例子: 示例1:

我在这里使用N3936作为参考(如果C++14中的任何文本不同,请更正此问题)

根据3.10左值和右值,我们有:

每个表达式都恰好属于该分类法中的一个基本分类:lvalue、xvalue或prvalue

然而,左值的定义如下:

左值[…]表示函数或对象

在4.1左值到右值转换中,文本出现:

[…]在所有其他情况下,转换结果根据以下规则确定: [...] 否则,glvalue指示的对象中包含的值就是prvalue结果

我的问题是:如果左值不指定对象,代码中会发生什么?有两个典型的例子:

示例1:

int *p = nullptr;
*p;
int &q = *p;
int a = *p;
int arr[4];
int *p = arr + 4;
*p;
int &q = *p;
std::sort(arr, &q);
示例2:

int *p = nullptr;
*p;
int &q = *p;
int a = *p;
int arr[4];
int *p = arr + 4;
*p;
int &q = *p;
std::sort(arr, &q);
哪些线(如果有)格式不正确和/或导致未定义的行为

参考示例1:
*p
是左值吗?根据我的第一句话,它一定是。但是,我的第二个引语不包括它,因为
*p
没有指定对象。(它当然不是xvalue或prvalue)

但是,如果您将我的第二个引语解释为
*p
实际上是一个左值,那么左值到右值的转换规则根本不包括它。您可以采用catch-all规则“标准未定义的任何内容都是未定义的行为”,但是您必须允许存在空引用,只要没有执行左值到右值的转换

历史记录:此问题在中提出。在C++11中,DR232的分辨率确实出现了。从N3337左值到右值转换的报价:

如果glvalue引用的对象不是T类型的对象,也不是从T派生的类型的对象,或者如果该对象未初始化,则需要此转换的程序具有未定义的行为

这似乎仍然允许空引用存在-它只清除了在一个上执行左值到右值转换的问题


DR232的分辨率不再出现在N3797或N3936中。

不可能创建对null的引用或对数组末端元素的引用,因为第8.3.2节(从草案N3936中读取)指出:

引用应初始化为引用有效的对象或函数


然而,不清楚形成具有左值值值类别的表达式是否构成“引用的初始化”。恰恰相反,事实上,临时对象是对象,引用不是对象,因此不能说
*(a+n)
初始化了引用类型的临时对象。

我认为这个问题的答案虽然可能不是您真正想要的答案,这是未指定或未指定的,因此我们无法真正说明您提供的示例是否格式错误或根据当前的标准草案调用未定义的行为

我们可以通过查看
dr232
dr453
来了解这一点

告诉我们,标准在对空指针的解引用是否为未定义行为方面存在冲突:

该州至少有几个地方是通过 null指针产生未定义的行为:1.9[简介执行] 第4段给出了“取消对空指针的引用”作为示例 未定义的行为,8.3.2[dcl.ref]第4段(注释中)使用 这被认为是未定义的行为,作为 不存在“空引用”

然而,5.3.1[expr.unary.op]第1段描述了一元数 “*”运算符,并不是说如果 正如人们所期望的那样,操作数是空指针。此外,至少 其中一段给出了一个定义良好的空指针解引用行为: 5.2.8[解释类型ID]第2段

并引入了空左值的概念,它是在空指针或数组结束后的指针上独立的结果:

如果有的话。如果指针为空指针值(4.10[conv.ptr]),或 指向数组对象(5.7[expr.add])的最后一个元素上方的一个点, 结果是一个空的左值,不引用任何对象或对象 功能

并提出该类的lvaue到rvalue的转换是未定义的行为

告诉我们我们不知道什么是有效对象:

什么是“有效”对象?尤其是表达式“有效对象” 似乎排除了未初始化的对象,但对核心问题的响应 363清楚地表明这不是目的

并指出将引用绑定到空值是未定义的行为

如果引用直接绑定到的左值既不指定 适当类型的现有对象或功能(8.5.3 [dcl.init.ref]),也不是适当大小和对齐的内存区域 包含引用类型的对象(1.8[intro.object],3.8 [basic.life],3.9[basic.types]),行为未定义

并在建议书中包括以下示例:

int& f(int&);
int& g();

extern int& ir3;
int* ip = 0;

int& ir1 = *ip;     // undefined behavior: null pointer
int& ir2 = f(ir3);  // undefined behavior: ir3 not yet initialized
int& ir3 = g();
int& ir4 = f(ir4);  // ill-formed: ir4 used in its own initializer
因此,如果我们想限制自己只处理意图,那么我觉得,并提供我们需要说明的信息,意图是空指针的左值到右值转换是未定义的行为,对空指针或不确定值的引用也是未定义的行为


现在,虽然这两份报告的决议都需要一段时间才能整理出来,但它们都很活跃,都有相对较新的更新。显然,委员会到目前为止并不反对报告的缺陷是实际缺陷这一主要前提。因此,在不了解这两个项目的情况下,这意味着无法使用当前的标准草案回答您的问题。

我认为其目的是