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

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

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

問(wèn)題描述

C++ 標(biāo)準(zhǔn)在 3.3.2聲明點(diǎn)"中包含一個(gè)半著名的令人驚訝"名稱(chēng)查找示例:

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

int x = x;

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

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

這實(shí)際上是未定義的行為嗎?

Is this actually undefined behaviour?

根據(jù)4.1左值到右值轉(zhuǎn)換",對(duì)未初始化的值執(zhí)行左值到右值轉(zhuǎn)換是未定義的行為.右手邊的 x 是否進(jìn)行了這種轉(zhuǎn)換?如果是這樣,該示例實(shí)際上是否會(huì)有未定義的行為?

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?

推薦答案

更新: 根據(jù)評(píng)論中的討論,我在此答案的末尾添加了更多證據(jù).

免責(zé)聲明:我承認(rèn)這個(gè)答案是推測(cè)性的.另一方面,C++11 標(biāo)準(zhǔn)的當(dāng)前表述似乎不允許提供更正式的答案.

這個(gè)問(wèn)答,發(fā)現(xiàn)C++11標(biāo)準(zhǔn)沒(méi)有正式指定什么值類(lèi)別 是每種語(yǔ)言結(jié)構(gòu)所期望的.下面我將主要關(guān)注內(nèi)置操作符,盡管問(wèn)題是關(guān)于初始化器.最終,我會(huì)將我從運(yùn)算符的情況得出的結(jié)論擴(kuò)展到初始化程序的情況.

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.

在內(nèi)置運(yùn)算符的情況下,盡管缺乏正式的規(guī)范,但在標(biāo)準(zhǔn)中發(fā)現(xiàn)了(非規(guī)范性的)證據(jù),預(yù)期規(guī)范是讓在需要值的任何地方以及未另行指定時(shí),均應(yīng)使用純右值.

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 段中的注釋說(shuō):

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

第 5 條中對(duì)每個(gè)內(nèi)置運(yùn)算符的討論指出了它產(chǎn)生的值的類(lèi)別以及它期望的操作數(shù)的值類(lèi)別.例如,內(nèi)置賦值運(yùn)算符期望左操作數(shù)是左值,右操作數(shù)是右值并產(chǎn)生左值作為結(jié)果. 用戶(hù)定義的運(yùn)算符是函數(shù),類(lèi)別它們期望和產(chǎn)生的值由它們的參數(shù)和返回類(lèi)型決定

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

另一方面,關(guān)于賦值運(yùn)算符的第 5.17 節(jié)沒(méi)有提到這一點(diǎn).但是,在注釋(第 5.17/1 段)中再次提到了執(zhí)行左值到右值轉(zhuǎn)換的可能性:

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):

因此,函數(shù)調(diào)用不應(yīng)干預(yù)左值到右值的轉(zhuǎn)換和與任何單個(gè)復(fù)合賦值運(yùn)算符相關(guān)的副作用

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

當(dāng)然,如果不期望右值,則此注釋將毫無(wú)意義.

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

另一個(gè)證據(jù)是在 4/8 中發(fā)現(xiàn)的,正如 Johannes Schaub 在對(duì)鏈接問(wèn)答:

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

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

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.

這似乎意味著對(duì)內(nèi)置運(yùn)算符的所有操作數(shù)都執(zhí)行左值到右值的轉(zhuǎn)換,除非另有說(shuō)明.這意味著,除非另有說(shuō)明,否則右值應(yīng)作為內(nèi)置運(yùn)算符的操作數(shù).

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.

推測(cè):

盡管初始化不是賦值,因此操作符沒(méi)有進(jìn)入討論,但我懷疑規(guī)范的這一領(lǐng)域受到上述相同問(wèn)題的影響.

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 段中找到支持這種信念的痕跡,關(guān)于引用的初始化(對(duì)于它來(lái)說(shuō)不需要左值初始化表達(dá)式的值):

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)、數(shù)組到指針 (4.2) 和函數(shù)到指針 (4.3) 的標(biāo)準(zhǔn)轉(zhuǎn)換,因此被抑制,當(dāng)這種對(duì)左值的直接綁定完成時(shí).

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.

通常"這個(gè)詞似乎暗示在初始化不是引用類(lèi)型的對(duì)象時(shí),應(yīng)該應(yīng)用左值到右值的轉(zhuǎn)換.

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.

因此,我認(rèn)為雖然對(duì)初始化器的期望值類(lèi)別的要求沒(méi)有明確規(guī)定(如果不是完全缺失),但根據(jù)證據(jù),假設(shè)預(yù)期規(guī)范是:

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:

在語(yǔ)言結(jié)構(gòu)需要值的地方,除非另有說(shuō)明,否則預(yù)期為純右值.

在此假設(shè)下,您的示例中需要進(jìn)行左值到右值的轉(zhuǎn)換,這將導(dǎo)致未定義行為.

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

其他證據(jù):

只是為了提供進(jìn)一步的證據(jù)來(lái)支持這個(gè)猜想,讓我們假設(shè)它錯(cuò)誤,這樣復(fù)制初始化確實(shí)不需要左值到右值的轉(zhuǎn)換,并考慮以下代碼(感謝jogojapan 貢獻(xiàn)):

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

這種不統(tǒng)一的行為對(duì)我來(lái)說(shuō)沒(méi)有多大意義.IMO 更有意義的是,無(wú)論何處需要值,都需要一個(gè)純右值.

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++ 標(biāo)準(zhǔn)的關(guān)鍵段落是 8.5/16:

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

——否則,被初始化的對(duì)象的初始值是(可能已轉(zhuǎn)換)初始化表達(dá)式的值.標(biāo)準(zhǔn)如有必要,將使用轉(zhuǎn)換(第 4 條)來(lái)轉(zhuǎn)換初始化表達(dá)式到 cv 非限定版本的目的地類(lèi)型;不考慮用戶(hù)定義的轉(zhuǎn)換.如果無(wú)法進(jìn)行轉(zhuǎn)換,初始化格式錯(cuò)誤.[ 筆記:cv1 T"類(lèi)型的表達(dá)式可以初始化cv2 T"類(lèi)型的對(duì)象獨(dú)立于 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 主要關(guān)注if必要"這一點(diǎn),但我也想強(qiáng)調(diào)類(lèi)型"這個(gè)詞.上面的段落提到了if必要"將使用標(biāo)準(zhǔn)轉(zhuǎn)換來(lái)轉(zhuǎn)換為目標(biāo)類(lèi)型,但沒(méi)有說(shuō)明類(lèi)別轉(zhuǎn)換:

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. 是否會(huì)在需要時(shí)執(zhí)行類(lèi)別轉(zhuǎn)換?
  2. 需要它們嗎?

關(guān)于第二個(gè)問(wèn)題,正如答案的原始部分所討論的,C++11標(biāo)準(zhǔn)目前沒(méi)有指定是否需要類(lèi)別轉(zhuǎn)換,因?yàn)闆](méi)有提到復(fù)制初始化是否需要純右值作為初始化程序.因此,不可能給出明確的答案.但是,我相信我提供了足夠的證據(jù)來(lái)假設(shè)這是預(yù)期的規(guī)范,因此答案是是".

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".

至于第一個(gè)問(wèn)題,我認(rèn)為答案也是是"似乎是合理的.如果它是否",顯然正確的程序?qū)⑹歉袷藉e(cuò)誤的:

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)

總結(jié)起來(lái)(A1 =問(wèn)題1的答案",A2 =問(wèn)題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 無(wú)關(guān)緊要:沒(méi)有 UB,但是第一個(gè)示例的奇怪情況(例如 z = y 給出 UB,但不是 z = x 即使 x == y) 出現(xiàn).如果 A2 是是",另一方面,A1 變得至關(guān)重要;然而,已經(jīng)提供了足夠的證據(jù)來(lái)證明它會(huì)是".

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".

因此,我的論點(diǎn)是 A1 = "Yes" 和 A2 = "Yes",我們應(yīng)該有未定義行為.

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

進(jìn)一步的證據(jù):

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

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 段說(shuō)將左值到右值轉(zhuǎn)換應(yīng)用于未初始化的對(duì)象"會(huì)導(dǎo)致未定義的行為;這應(yīng)該改寫(xiě)為具有不確定值的對(duì)象.

[...] 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 段的擬議措辭說(shuō):

In particular, the proposed wording for Paragraph 4.1 says:

當(dāng)在未計(jì)算的操作數(shù)或其子表達(dá)式(第 5 條 [expr])中發(fā)生左值到右值的轉(zhuǎn)換時(shí),引用對(duì)象中包含的值不會(huì)被訪問(wèn).在所有其他情況下,轉(zhuǎn)換結(jié)果根據(jù)以下規(guī)則確定:

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,結(jié)果是一個(gè)空指針常量(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 具有類(lèi)類(lèi)型,則轉(zhuǎn)換會(huì)從泛左值復(fù)制初始化 T 類(lèi)型的臨時(shí)值,并且轉(zhuǎn)換的結(jié)果是臨時(shí)值的純右值.

— 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.

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

— 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 限定的)無(wú)符號(hào)字符類(lèi)型(3.9.1 [basic.fundamental]),并且泛左值所指的對(duì)象包含不確定值(5.3.4 [expr.new], 8.5 [dcl.init], 12.6.2 [class.base.init]),并且該對(duì)象沒(méi)有自動(dòng)存儲(chǔ)持續(xù)時(shí)間或者泛左值是一元 & 的操作數(shù).運(yùn)算符或者它被綁定到一個(gè)引用,結(jié)果是一個(gè)未指定的值.[腳注:每次將左值到右值轉(zhuǎn)換應(yīng)用于對(duì)象時(shí),該值可能會(huì)有所不同.分配給寄存器的具有不確定值的無(wú)符號(hào)字符對(duì)象可能會(huì)陷入陷阱.——結(jié)束腳注]

— 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]

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

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

— 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.

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

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

相關(guān)文檔推薦

Algorithm to convert RGB to HSV and HSV to RGB in range 0-255 for both(將 RGB 轉(zhuǎn)換為 HSV 并將 HSV 轉(zhuǎn)換為 RGB 的算法,范圍為 0-255)
How to convert an enum type variable to a string?(如何將枚舉類(lèi)型變量轉(zhuǎn)換為字符串?)
When to use inline function and when not to use it?(什么時(shí)候使用內(nèi)聯(lián)函數(shù),什么時(shí)候不使用?)
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 仍然相關(guān)嗎?)
主站蜘蛛池模板: 精品一区二区三区在线观看 | 免费在线观看www | 国产农村妇女aaaaa视频 | 午夜精品久久久久久久久久蜜桃 | 性做久久久久久 | 日本一级淫片色费放 | 深夜福利网 | 日韩黄色在线观看 | 精品福利一区 | 精品一区在线播放 | 久久久久亚洲 | 成人三级小说 | 四虎影视av | 天天操夜 | 一区二区不卡视频 | 亚洲小视频在线观看 | 色婷婷视频在线观看 | 成人免费在线观看 | 在线看av网址 | 精品少妇一区二区三区免费观 | 欧美性猛交99久久久久99按摩 | 国产小视频在线观看 | 亚洲第一黄网 | 日韩精品免费视频 | 欧美日韩亚洲综合 | 午夜美女福利视频 | 国产香蕉视频在线观看 | 小镇姑娘国语版在线观看免费 | 亚洲精品久久久久avwww潮水 | a在线观看 | 日韩精品少妇 | 中文在线播放 | 亚洲免费视频网站 | 久久精品一区二区国产 | 欧美一区二区三区四区五区 | 欧美视频一区二区三区 | 国产美女福利 | 免费视频一区 | 免费黄色av | 九九热精品 | 黄色片视频免费 |