久久久久久久av_日韩在线中文_看一级毛片视频_日本精品二区_成人深夜福利视频_武道仙尊动漫在线观看

初始化是否需要左值到右值的轉換?是`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 仍然相關嗎?)
主站蜘蛛池模板: 久久久久久综合 | 一区二区视屏 | 久久在线视频 | 日韩一区二区在线播放 | 欧美日韩在线一区二区 | 95国产精品 | 国产亚洲一区精品 | 欧美精品一区在线 | 日韩高清一区二区 | 亚洲欧美国产视频 | 欧美婷婷 | 欧美一级毛片久久99精品蜜桃 | 成人在线视频免费观看 | 成人国产精品久久 | 久久88| 亚洲网站在线观看 | 天天综合操 | 国产乱码精品一品二品 | 国内精品视频在线 | 精品av| 日本淫视频 | 欧美久久一区 | 精品国产欧美一区二区 | 孰女乱色一区二区三区 | 久久国产一区二区三区 | 在线观看欧美日韩视频 | 欧美日韩国产在线观看 | www.久久| 亚洲色图综合 | 日日操av | 亚洲国产一区二区三区, | 亚洲三区视频 | 亚洲精品久久久久久久久久久 | 亚洲444eee在线观看 | 午夜码电影 | 91在线视频观看 | 中文字幕第一页在线 | av在线一区二区三区 | 黑人久久 | 国产精品99久 | 亚洲日本欧美日韩高观看 |