'? :'의 반환 유형 (삼항 조건 연산자)


208

첫 번째가 왜 참조를 반환합니까?

int x = 1;
int y = 2;
(x > y ? x : y) = 100;

두 번째는 그렇지 않지만?

int x = 1;
long y = 2;
(x > y ? x : y) = 100;

실제로 두 번째는 전혀 할당되지 않았습니다.


1
흠, 빵을 굽는 특별한 경우를 찾는 것과 같은 일이 한 번도 이루어지지
않았습니다


식에 유형을 할당하면 하나 이상의 항이 캐스트됨을 의미하므로이 항은 더 이상 l 값이 아닙니다.
Yves Daoust

답변:


173

식에는 반환 형식이 없으며 형식과 최신 C ++ 표준에서 알려진 것처럼 값 범주가 있습니다.

조건식은 lvalue 또는 rvalue 일 수 있습니다 . 이것이 가치 범주입니다. ( C++11우리는 lvalues, xvalues ​​및 prvalues 가 있기 때문에 다소 단순화 된 것입니다.)

매우 광범위하고 간단한 용어로, lvalue 는 메모리의 객체를 나타내며 rvalue 는 메모리의 객체에 반드시 연결될 필요는없는 값일뿐입니다.

대입 식은 객체에 값을 대입하므로 할당되는 것은 lvalue 이어야합니다 .

조건식 ( ?:)이 lvalue (넓고 간단한 용어로)가 되려면 두 번째와 세 번째 피연산자가 같은 유형의 lvalue 여야합니다 . 조건부 표현식의 유형 및 값 범주는 컴파일시 결정되며 조건이 true인지 여부에 따라 적절해야하기 때문입니다. 피연산자 중 하나가 다른 일치하는 다른 형식으로 변환해야하는 경우 다음 조건식은 될 수 없다 좌변 되지 않을 것이 변환의 결과로 좌변 .

ISO / IEC 14882 : 2011 참조 :

3.10 [basic.lval] L 값 및 r 값 (값 범주 정보)

5.15 [expr.cond] 조건부 연산자 (조건부 표현식의 유형 및 값 범주에 대한 규칙)

5.17 [expr.ass] 대입 및 복합 대입 연산자 (대입의 lh는 수정 가능한 lvalue 여야 함)


3
그리고 xvalue와 prvalue를 읽을 때 (당신의 대답 전에 그것들을 듣지 못했기 때문에) 나는이 편리한 SO 게시물을 보았습니다 : stackoverflow.com/questions/3601602/…
fluffy

an rvalue is just a value that may not necessarily be *attached* to an object in memory.더 간단한 용어로 이것을 설명 할 수 있습니까? . 또한 무엇을 의미 type and value *category*합니까?. 감사합니다
Mr.Anubis

@SoulReaper : prvalue, xvalue, glvalue가치 범주입니다.
Xeo

@ Xeo 도움을 주셔서 감사하지만 rvalue가 의미하는 바 는 메모리의 객체에 반드시 첨부 할 필요는없는 값 일뿐입니다. ? 예를 들어?
Mr.Anubis

@SoulReaper : 나는 그가 것들에 대해 이야기하고 생각처럼 true, this, enum값을. 이러한 것들은 prvalues ​​( "순수한"rvalues)이지만 메모리에 존재하지 않습니다.
Xeo

57

삼항 ?:표현식의 유형은 두 번째 및 세 번째 인수의 공통 유형입니다. 두 유형이 모두 같으면 참조가 다시 제공됩니다. 서로 전환 할 수있는 경우 하나를 선택하고 다른 하나를 변환합니다 (이 경우 승격). 임시 (변환 / 승격 된 변수)에 대한 lvalue 참조를 리턴 할 수 없으므로 해당 유형은 값 유형입니다.


그러나 y는 x보다 크므로이 특별한 경우에는 승격 할 필요가 없으며 y에 대한 참조를 반환 할 수 있습니다. 흠 ...하지만 동의 할 것입니다. 이상 할 것입니다.
Yola

1
@ Mr.TAMER : 표준을 파고 들었습니다. : <
Xeo

3
@Yola : 형식은 C ++에서 컴파일 시간 개념이므로 식 의 실제 반환 은 중요하지 않습니다.
Xeo

1
당신은 참조를 얻지 못하고 lvalue를 얻습니다.
Suma

1
@Xeo : C ++ 용어는 아니지만;)
Sebastian Mach

19

유형이 일치하도록 유형 을 암시 적으로 승격시켜야하고 (양측이 동일한 유형이 아니기 때문에 ) 임시 값을 작성 해야하므로 lvalue를 리턴 할 수 없습니다 .xy:


표준은 무엇을 말합니까? ( n1905 )

식 5.17 대입 및 복합 대입 연산자

5.17 / 3

두 번째 피연산자와 세 번째 피연산자가 서로 다른 유형을 가지고 있고 클래스 유형이 있거나 (가능하면 cv-qualified) 클래스 유형을 가진 경우, 각 피연산자 각각을 다른 유형의 피연산자로 변환하려고 시도합니다. 유형 T1의 피연산자 표현식 E1이 유형 T2의 피연산자 표현식 E2와 일치하도록 변환 될 수 있는지 여부를 판별하는 프로세스는 다음과 같이 정의됩니다.

— E2가 lvalue 인 경우 : E1을 암시 적으로 "T2에 대한 참조"유형으로 변환 할 수있는 경우 E1을 E2와 일치하도록 변환 할 수 있습니다 (변환에서 참조는 직접 바인딩해야 함 (8.5.3)). )를 E1에

— E2가 rvalue이거나 위의 변환을 수행 할 수없는 경우 :

— E1 및 E2에 클래스 유형이 있고 기본 클래스 유형이 동일하거나 하나가 다른 클래스의 기본 클래스 인 경우 : T2 클래스가 동일한 유형이거나 기본 클래스의 클래스 인 경우 E1이 E2와 일치하도록 변환 될 수 있습니다. , T1의 클래스 및 T2의 cv-qualification은 T1의 cv-qualification과 동일한 cv-qualification이거나 더 큰 cv-qualification입니다. 변환이 적용되는 경우, E1은 원래 소스 클래스 오브젝트 (또는 해당 하위 오브젝트)를 여전히 참조하는 T2 유형의 rvalue로 변경됩니다. [ 참고 : 즉, 복사가 이루어지지 않습니다. — end note ] E1에서 T2 유형의 임시를 복사 초기화하고 해당 임시를 변환 된 피연산자로 사용합니다.

그렇지 않은 경우 (예 : E1또는 E2에 클래스 유형이 아닌 경우 또는 둘 다 클래스 유형이 있지만 기본 클래스가 같거나 다른 클래스의 기본 클래스가 아닌 경우) : E1이 가능한 경우 E1은 E2와 일치하도록 변환 될 수 있습니다 E2가 rvalue로 변환 된 경우 표현식 E2가 갖는 유형 (또는 E2가 rvalue 인 경우 보유한 유형)으로 내재적으로 변환됩니다.

이 프로세스를 사용하여, 제 2 피연산자가 제 3 피연산자와 일치하도록 변환 될 수 있는지, 그리고 제 3 피연산자가 제 2 피연산자와 일치하도록 변환 될 수 있는지 여부가 결정된다. 둘 다 변환 할 수 있거나 변환 할 수 있지만 변환이 모호한 경우 프로그램이 잘못 구성됩니다. 둘 다 변환 할 수 없으면 피연산자는 변경되지 않은 상태로 유지되며 아래에 설명 된대로 추가 검사가 수행됩니다. 정확히 하나의 변환이 가능하면 해당 변환이 선택한 피연산자에 적용되고 변환 된 피연산자가이 섹션의 나머지 부분에 대해 원래 피연산자 대신 사용됩니다.


5.17 / 4

두 번째 및 세 번째 피연산자가 lvalues이고 동일한 유형을 갖는 경우 결과는 해당 유형이며 lvalue이며 두 번째 또는 세 번째 피연산자가 비트 필드이거나 둘 다 비트 인 경우 비트 필드입니다. 필드.


5.17 / 5

그렇지 않으면 결과는 rvalue입니다. 두 번째 피연산자와 세 번째 피연산자가 동일한 유형을 가지고 있지 않거나 클래스 유형이 있거나 (종종 cv-qualified) 클래스 유형을 갖는 경우, 과부하 해결을 사용하여 피연산자에 적용 할 변환 (있는 경우)을 판별합니다 (13.3.1.2, 13.6). . 과부하 해결에 실패하면 프로그램이 잘못 구성됩니다. 그렇지 않으면 결정된 변환이 적용되고 변환 된 피연산자가이 섹션의 나머지 부분에 대해 원래 피연산자 대신 사용됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.