pbootcms网站模板|日韩1区2区|织梦模板||网站源码|日韩1区2区|jquery建站特效-html5模板网

初始化是否需要左值到右值的轉換?是`int x = x;`

Does initialization entail lvalue-to-rvalue conversion? Is `int x = x;` UB?(初始化是否需要左值到右值的轉換?是`int x = x;` UB 嗎?)
本文介紹了初始化是否需要左值到右值的轉換?是`int x = x;` UB 嗎?的處理方法,對大家解決問題具有一定的參考價值,需要的朋友們下面隨著小編來一起學習吧!

問題描述

C++ 標準在 3.3.2聲明點"中包含一個半著名的令人驚訝"名稱查找示例:

The C++ standard contains a semi-famous example of "surprising" name lookup in 3.3.2, "Point of declaration":

int x = x;

這用自身初始化 x,它(作為原始類型)未初始化,因此具有不確定的值(假設它是一個自動變量).

This initializes x with itself, which (being a primitive type) is uninitialized and thus has an indeterminate value (assuming it is an automatic variable).

這實際上是未定義的行為嗎?

Is this actually undefined behaviour?

根據4.1左值到右值轉換",對未初始化的值執行左值到右值轉換是未定義的行為.右手邊的 x 是否進行了這種轉換?如果是這樣,該示例實際上是否會有未定義的行為?

According to 4.1 "Lvalue-to-rvalue conversion", it is undefined behaviour to perform lvalue-to-rvalue conversion on an uninitialized value. Does the right-hand x undergo this conversion? If so, would the example actually have undefined behaviour?

推薦答案

更新: 根據評論中的討論,我在此答案的末尾添加了更多證據.

免責聲明:我承認這個答案是推測性的.另一方面,C++11 標準的當前表述似乎不允許提供更正式的答案.

這個問答,發現C++11標準沒有正式指定什么值類別 是每種語言結構所期望的.下面我將主要關注內置操作符,盡管問題是關于初始化器.最終,我會將我從運算符的情況得出的結論擴展到初始化程序的情況.

In the context of this Q&A, it has emerged that the C++11 Standard fails to formally specify what value categories are expected by each language construct. In the following I will mostly focus on built-in operators, although the question is about initializers. Eventually, I will end up extending the conclusions I drew for the case of operators to the case of initializers.

在內置運算符的情況下,盡管缺乏正式的規范,但在標準中發現了(非規范性的)證據,預期規范是讓在需要值的任何地方以及未另行指定時,均應使用純右值.

In the case of built-in operators, in spite of the lack of a formal specification, (non-normative) evidences are found in the Standard that the intended specification is to let prvalues be expected wherever a value is needed, and when not specified otherwise.

例如,第 3.10/1 段中的注釋說:

For instance, a note in Paragraph 3.10/1 says:

第 5 條中對每個內置運算符的討論指出了它產生的值的類別以及它期望的操作數的值類別.例如,內置賦值運算符期望左操作數是左值,右操作數是右值并產生左值作為結果. 用戶定義的運算符是函數,類別它們期望和產生的值由它們的參數和返回類型決定

The discussion of each built-in operator in Clause 5 indicates the category of the value it yields and the value categories of the operands it expects. For example, the built-in assignment operators expect that the left operand is an lvalue and that the right operand is a prvalue and yield an lvalue as the result. User-defined operators are functions, and the categories of values they expect and yield are determined by their parameter and return types

另一方面,關于賦值運算符的第 5.17 節沒有提到這一點.但是,在注釋(第 5.17/1 段)中再次提到了執行左值到右值轉換的可能性:

Section 5.17 on assignment operators, on the other hand, does not mention this. However, the possibility of performing an lvalue-to-rvalue conversion is mentioned, again in a note (Paragraph 5.17/1):

因此,函數調用不應干預左值到右值的轉換和與任何單個復合賦值運算符相關的副作用

Therefore, a function call shall not intervene between the lvalue-to-rvalue conversion and the side effect associated with any single compound assignment operator

當然,如果不期望右值,則此注釋將毫無意義.

Of course, if no rvalue were expected, this note would be meaningless.

另一個證據是在 4/8 中發現的,正如 Johannes Schaub 在對鏈接問答:

Another evidence is found in 4/8, as pointed out by Johannes Schaub in the comments to linked Q&A:

在某些情況下,某些轉換會被抑制.例如,不在一元 & 的操作數上進行左值到右值的轉換.操作員.在這些運算符和上下文的描述中給出了特定的例外情況.

There are some contexts where certain conversions are suppressed. For example, the lvalue-to-rvalue conversion is not done on the operand of the unary & operator. Specific exceptions are given in the descriptions of those operators and contexts.

這似乎意味著對內置運算符的所有操作數都執行左值到右值的轉換,除非另有說明.這意味著,除非另有說明,否則右值應作為內置運算符的操作數.

This seems to imply that lvalue-to-rvalue conversion is performed on all operands of built-in operators, except when specified otherwise. This would mean, in turn, that rvalues are expected as operands of built-in operators unless specified otherwise.

推測:

盡管初始化不是賦值,因此操作符沒有進入討論,但我懷疑規范的這一領域受到上述相同問題的影響.

Even though initialization is not assignment, and therefore operators do not enter the discussion, my suspicion is that this area of the specification is affected by the very same problem described above.

甚至可以在第 8.5.2/5 段中找到支持這種信念的痕跡,關于引用的初始化(對于它來說不需要左值初始化表達式的值):

Traces supporting this belief can be found even in Paragraph 8.5.2/5, about the initialization of references (for which the value of the lvalue initializer expression is not needed):

不需要通常左值到右值 (4.1)、數組到指針 (4.2) 和函數到指針 (4.3) 的標準轉換,因此被抑制,當這種對左值的直接綁定完成時.

The usual lvalue-to-rvalue (4.1), array-to-pointer (4.2), and function-to-pointer (4.3) standard conversions are not needed, and therefore are suppressed, when such direct bindings to lvalues are done.

通常"這個詞似乎暗示在初始化不是引用類型的對象時,應該應用左值到右值的轉換.

The word "usual" seems to imply that when initializing objects which are not of a reference type, lvalue-to-rvalue conversion is meant to apply.

因此,我認為雖然對初始化器的期望值類別的要求沒有明確規定(如果不是完全缺失),但根據證據,假設預期規范是:

Therefore, I believe that although requirements on the expected value category of initializers are ill-specified (if not completely missing), on the grounds of the evidences provided it makes sense to assume that the intended specification is that:

在語言結構需要值的地方,除非另有說明,否則預期為純右值.

在此假設下,您的示例中需要進行左值到右值的轉換,這將導致未定義行為.

Under this assumption, an lvalue-to-rvalue conversion would be required in your example, and that would lead to Undefined Behavior.

其他證據:

只是為了提供進一步的證據來支持這個猜想,讓我們假設它錯誤,這樣復制初始化確實不需要左值到右值的轉換,并考慮以下代碼(感謝jogojapan 貢獻):

Just to provide further evidence to support this conjecture, let's assume it wrong, so that no lvalue-to-rvalue conversion is indeed required for copy-initialization, and consider the following code (thanks to jogojapan for contributing):

int y;
int x = y; // No UB
short t;
int u = t; // UB! (Do not like this non-uniformity, but could accept it)
int z;
z = x; // No UB (x is not uninitialized)
z = y; // UB! (Assuming assignment operators expect a prvalue, see above)
       // This would be very counterintuitive, since x == y

這種不統一的行為對我來說沒有多大意義.IMO 更有意義的是,無論何處需要值,都需要一個純右值.

This non-uniform behavior does not make a lot of sense to me. What makes more sense IMO is that wherever a value is required, a prvalue is expected.

此外,正如 Jesse Good 在他的回答中正確指出的那樣,C++ 標準的關鍵段落是 8.5/16:

Moreover, as Jesse Good correctly points out in his answer, the key Paragraph of the C++ Standard is 8.5/16:

——否則,被初始化的對象的初始值是(可能已轉換)初始化表達式的值.標準如有必要,將使用轉換(第 4 條)來轉換初始化表達式到 cv 非限定版本的目的地類型;不考慮用戶定義的轉換.如果無法進行轉換,初始化格式錯誤.[ 筆記:cv1 T"類型的表達式可以初始化cv2 T"類型的對象獨立于 cv 限定符 cv1 和 cv2.

— Otherwise, the initial value of the object being initialized is the (possibly converted) value of the initializer expression. Standard conversions (Clause 4) will be used, if necessary, to convert the initializer expression to the cv-unqualified version of the destination type; no user-defined conversions are considered. If the conversion cannot be done, the initialization is ill-formed. [ Note: An expression of type "cv1 T" can initialize an object of type "cv2 T" independently of the cv-qualifiers cv1 and cv2.

然而,雖然 Jesse 主要關注if必要"這一點,但我也想強調類型"這個詞.上面的段落提到了if必要"將使用標準轉換來轉換為目標類型,但沒有說明類別轉換:

However, while Jesse mainly focuses on the "if necessary" bit, I would also like to stress the word "type". The paragraph above mentions that standard conversions will be used "if necessary" to convert to the destination type, but does not say anything about category conversions:

  1. 是否會在需要時執行類別轉換?
  2. 需要它們嗎?

關于第二個問題,正如答案的原始部分所討論的,C++11標準目前沒有指定是否需要類別轉換,因為沒有提到復制初始化是否需要純右值作為初始化程序.因此,不可能給出明確的答案.但是,我相信我提供了足夠的證據來假設這是預期的規范,因此答案是是".

For what concerns the second question, as discussed in the original part of the answer, the C++11 Standard currently does not specify whether category conversions are needed or not, because nowhere it is mentioned whether copy-initialization expects a prvalue as an initializer. Thus, a clear-cut answer is impossible to give. However, I believe I provided enough evidence to assume this to be the intended specification, so that the answer would be "Yes".

至于第一個問題,我認為答案也是是"似乎是合理的.如果它是否",顯然正確的程序將是格式錯誤的:

As for the first question, it seems reasonable to me that the answer is "Yes" as well. If it were "No", obviously correct programs would be ill-formed:

int y = 0;
int x = y; // y is lvalue, prvalue expected (assuming the conjecture is correct)

總結起來(A1 =問題1的答案",A2 =問題2的答案"):

To sum it up (A1 = "Answer to question 1", A2 = "Answer to question 2"):

          | A2 = Yes   | A2 = No |
 ---------|------------|---------|
 A1 = Yes |     UB     |  No UB  | 
 A1 = No  | ill-formed |  No UB  |
 ---------------------------------

如果 A2 為否",則 A1 無關緊要:沒有 UB,但是第一個示例的奇怪情況(例如 z = y 給出 UB,但不是 z = x 即使 x == y) 出現.如果 A2 是是",另一方面,A1 變得至關重要;然而,已經提供了足夠的證據來證明它會是".

If A2 is "No", A1 does not matter: there's no UB, but the bizarre situations of the first example (e.g. z = y giving UB, but not z = x even though x == y) show up. If A2 is "Yes", on the other hand, A1 becomes crucial; yet, enough evidence has been given to prove it would be "Yes".

因此,我的論點是 A1 = "Yes" 和 A2 = "Yes",我們應該有未定義行為.

Therefore, my thesis is that A1 = "Yes" and A2 = "Yes", and we should have Undefined Behavior.

進一步的證據:

這個缺陷報告(由 Jesse Good 提供a>) 提出了一個旨在在這種情況下提供未定義行為的更改:

This defect report (courtesy of Jesse Good) proposes a change that is aimed at giving Undefined Behavior in this case:

[...] 此外,4.1 [conv.lval] 第 1 段說將左值到右值轉換應用于未初始化的對象"會導致未定義的行為;這應該改寫為具有不確定值的對象.

[...] In addition, 4.1 [conv.lval] paragraph 1 says that applying the lvalue-to-rvalue conversion to an "object [that] is uninitialized" results in undefined behavior; this should be rephrased in terms of an object with an indeterminate value.

特別是,第 4.1 段的擬議措辭說:

In particular, the proposed wording for Paragraph 4.1 says:

當在未計算的操作數或其子表達式(第 5 條 [expr])中發生左值到右值的轉換時,引用對象中包含的值不會被訪問.在所有其他情況下,轉換結果根據以下規則確定:

When an lvalue-to-rvalue conversion occurs in an unevaluated operand or a subexpression thereof (Clause 5 [expr]) the value contained in the referenced object is not accessed. In all other cases, the result of the conversion is determined according to the following rules:

——如果 T 是(可能有 cv 限定的)std::nullptr_t,結果是一個空指針常量(4.10 [conv.ptr]).

— If T is (possibly cv-qualified) std::nullptr_t, the result is a null pointer constant (4.10 [conv.ptr]).

——否則,如果泛左值 T 具有類類型,則轉換會從泛左值復制初始化 T 類型的臨時值,并且轉換的結果是臨時值的純右值.

— Otherwise, if the glvalue T has a class type, the conversion copy-initializes a temporary of type T from the glvalue and the result of the conversion is a prvalue for the temporary.

——否則,如果泛左值引用的對象包含無效的指針值(3.7.4.2 [basic.stc.dynamic.deallocation], 3.7.4.3 [basic.stc.dynamic.safety]),則行為為實現定義.

— Otherwise, if the object to which the glvalue refers contains an invalid pointer value (3.7.4.2 [basic.stc.dynamic.deallocation], 3.7.4.3 [basic.stc.dynamic.safety]), the behavior is implementation-defined.

——否則,如果 T 是(可能是 cv 限定的)無符號字符類型(3.9.1 [basic.fundamental]),并且泛左值所指的對象包含不確定值(5.3.4 [expr.new], 8.5 [dcl.init], 12.6.2 [class.base.init]),并且該對象沒有自動存儲持續時間或者泛左值是一元 & 的操作數.運算符或者它被綁定到一個引用,結果是一個未指定的值.[腳注:每次將左值到右值轉換應用于對象時,該值可能會有所不同.分配給寄存器的具有不確定值的無符號字符對象可能會陷入陷阱.——結束腳注]

— Otherwise, if T is a (possibly cv-qualified) unsigned character type (3.9.1 [basic.fundamental]), and the object to which the glvalue refers contains an indeterminate value (5.3.4 [expr.new], 8.5 [dcl.init], 12.6.2 [class.base.init]), and that object does not have automatic storage duration or the glvalue was the operand of a unary & operator or it was bound to a reference, the result is an unspecified value. [Footnote: The value may be different each time the lvalue-to-rvalue conversion is applied to the object. An unsigned char object with indeterminate value allocated to a register might trap. —end footnote]

否則,如果泛左值引用的對象包含不確定值,則行為未定義.

——否則,如果泛左值具有(可能有 cv 限定的)類型 std::nullptr_t,則純右值結果是空指針常量 (4.10 [conv.ptr]).否則,泛左值所指示的對象中包含的值就是純右值結果.

— Otherwise, if the glvalue has (possibly cv-qualified) type std::nullptr_t, the prvalue result is a null pointer constant (4.10 [conv.ptr]). Otherwise, the value contained in the object indicated by the glvalue is the prvalue result.

這篇關于初始化是否需要左值到右值的轉換?是`int x = x;` UB 嗎?的文章就介紹到這了,希望我們推薦的答案對大家有所幫助,也希望大家多多支持html5模板網!

【網站聲明】本站部分內容來源于互聯網,旨在幫助大家更快的解決問題,如果有圖片或者內容侵犯了您的權益,請聯系我們刪除處理,感謝您的支持!

相關文檔推薦

Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both(將 RGB 轉換為 HSV 并將 HSV 轉換為 RGB 的算法,范圍為 0-255)
How to convert an enum type variable to a string?(如何將枚舉類型變量轉換為字符串?)
When to use inline function and when not to use it?(什么時候使用內聯函數,什么時候不使用?)
Examples of good gotos in C or C++(C 或 C++ 中好的 goto 示例)
Significance of ios_base::sync_with_stdio(false); cin.tie(NULL);(ios_base::sync_with_stdio(false) 的意義;cin.tie(NULL);)
Is TCHAR still relevant?(TCHAR 仍然相關嗎?)
主站蜘蛛池模板: 亿诺千企网-企业核心产品贸易| 微信小程序定制,广州app公众号商城网站开发公司-广东锋火 | 防火板_饰面耐火板价格、厂家_品牌认准格林雅 | 好物生环保网、环保论坛 - 环保人的学习交流平台 | 123悬赏网_发布悬赏任务_广告任务平台 | 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 | 冰雕-冰雪世界-大型冰雕展制作公司-赛北冰雕官网 | 优秀的临床医学知识库,临床知识库,医疗知识库,满足电子病历四级要求,免费试用 | 高中学习网-高考生信息学习必备平台 | 哲力实业_专注汽车涂料汽车漆研发生产_汽车漆|修补油漆品牌厂家 长沙一级消防工程公司_智能化弱电_机电安装_亮化工程专业施工承包_湖南公共安全工程有限公司 | 工程管道/塑料管材/pvc排水管/ppr给水管/pe双壁波纹管等品牌管材批发厂家-河南洁尔康建材 | 直读光谱仪,光谱分析仪,手持式光谱仪,碳硫分析仪,创想仪器官网 | 自清洗过滤器-全自动自清洗过反冲洗过滤器 - 中乂(北京)科技有限公司 | 苏州西朗门业-欧盟CE|莱茵UL双认证的快速卷帘门品牌厂家 | 烘干设备-热泵烘干机_广东雄贵能源设备有限公司 | 视频教程导航网_视频教程之家_视频教程大全_最新视频教程分享发布平台 | 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 隧道窑炉,隧道窑炉厂家-山东艾瑶国际贸易| 齿式联轴器-弹性联轴器-联轴器厂家-江苏诺兴传动联轴器制造有限公司 | 哲力实业_专注汽车涂料汽车漆研发生产_汽车漆|修补油漆品牌厂家 长沙一级消防工程公司_智能化弱电_机电安装_亮化工程专业施工承包_湖南公共安全工程有限公司 | 甲级防雷检测仪-乙级防雷检测仪厂家-上海胜绪电气有限公司 | 汝成内控-行政事业单位内部控制管理服务商 | 超细粉碎机|超微气流磨|气流分级机|粉体改性设备|超微粉碎设备-山东埃尔派粉碎机厂家 | 砂尘试验箱_淋雨试验房_冰水冲击试验箱_IPX9K淋雨试验箱_广州岳信试验设备有限公司 | 油冷式_微型_TDY电动滚筒_外装_外置式电动滚筒厂家-淄博秉泓机械有限公司 | 干粉砂浆设备-干粉砂浆生产线-干混-石膏-保温砂浆设备生产线-腻子粉设备厂家-国恒机械 | 洁净棚-洁净工作棚-无菌室-净化工程公司_北京卫护科技有限公司 | 插针变压器-家用电器变压器-工业空调变压器-CD型电抗器-余姚市中驰电器有限公司 | 数码听觉统合训练系统-儿童感觉-早期言语评估与训练系统-北京鑫泰盛世科技发展有限公司 | 真空包装机-诸城市坤泰食品机械有限公司| 神马影院-实时更新秒播 | RTO换向阀_VOC高温阀门_加热炉切断阀_双偏心软密封蝶阀_煤气蝶阀_提升阀-湖北霍科德阀门有限公司 | 螺旋叶片_螺旋叶片成型机_绞龙叶片_莱州源泽机械制造有限公司 | 捷码低代码平台 - 3D数字孪生_大数据可视化开发平台「免费体验」 | 消泡剂_水处理消泡剂_切削液消泡剂_涂料消泡剂_有机硅消泡剂_广州中万新材料生产厂家 | 高压油管,液压接头,液压附件-烟台市正诚液压附件 | 龙门加工中心-数控龙门加工中心厂家价格-山东海特数控机床有限公司_龙门加工中心-数控龙门加工中心厂家价格-山东海特数控机床有限公司 | 昆明网络公司|云南网络公司|昆明网站建设公司|昆明网页设计|云南网站制作|新媒体运营公司|APP开发|小程序研发|尽在昆明奥远科技有限公司 | 2025黄道吉日查询、吉时查询、老黄历查询平台- 黄道吉日查询网 | 证券新闻,热播美式保罗1984第二部_腾讯1080p-仁爱影院 | 淘剧影院_海量最新电视剧,免费高清电影随心观看 |