왜 C ++에는 부울에 대해 && = 또는 || =가 없습니까?


126

거기에 "매우 나쁜 일" 일어날 수있는 &&=||=에 대한 문법 설탕을 사용 하였다 bool foo = foo && bar와는 bool foo = foo || bar?


5
이 다른 질문을보십시오 : stackoverflow.com/questions/2324549/… 그것은 Java에 관한 것이지만 C 계보를 공유하며 동일한 인수가 대부분 적용됩니다.
jamesdlin

기본적으로, C ++는 그것을 가지고 있지 않습니다. 그들은 그것을 넣지 않았습니다. Ruby와 같은 언어는 그것을 가지고 있습니다. boo ...
Kache

2
하지만 루비에서는 어떤 유형의 x ||= yC ++와 거의 동일 하지 x = x ? x : y;않습니까? 즉, "아직 설정되지 않은 경우 y로 설정"입니다. 이것은 x ||= y(연산자 오버로딩을 제외하고) " (bool)y이미 설정되지 않은 한 x를로 설정" 하는 C 또는 C ++보다 훨씬 더 유용합니다 . 나는 그것을 위해 다른 연산자를 추가하고 싶지 않다. 그것은 약간 미약해 보인다. 그냥 쓰십시오 if (!x) x = (bool)y. 그러나 나는 bool그 한 유형에서만 실제로 유용한 추가 연산자를 원할만큼 변수를 실제로 사용하지 않습니다 .
Steve Jessop

1
나는 확실히 ++이없는 주된 이유의 C 해요 &&=또는 ||=C 그들을하지 않는 것을 단순히. 나는 C에 그것들이없는 이유는 기능이 충분히 유익하다고 간주되지 않았기 때문이라고 합리적으로 확신합니다.
Jonathan Leffler 2015

2
또한, 초보 형 bool foo = foo || bar;이기 때문에 ,이 표기법은를 foo평가하기 전에 초기화 되지 않았기 때문에 정의되지 않은 동작을 호출 foo || bar합니다. 물론 이것은 비슷한 것을 의도 한 것이며 bool foo = …initialization…; …; foo = foo || bar;질문은 유효한 것으로 간주됩니다.
Jonathan Leffler

답변:


73

A booltrue또는 falseC ++ 에서만 가능합니다 . 따라서 &=and 사용 |=은 상대적으로 안전합니다 (표기법이 특히 마음에 들지 않지만). 사실, 이들은 비트 연산보다는 논리 연산을 수행한다 (따라서 이들은 단락되지 않음)하지만, 이러한 비트 연산은 논리 연산 효과적으로 해당하는 잘 정의 된 맵핑을 수행 만큼 양쪽 피연산자 타입 인bool . 1

다른 사람들이 여기에서 말한 것과는 달리 boolC ++의 a는 2. 해당 값을에 할당 하면 표준에 따라 bool로 변환됩니다 true.

유효하지 않은 값을 가져 오는 유일한 방법 boolreinterpret_cast포인터 를 사용 하는 것 입니다 .

int i = 2;
bool b = *reinterpret_cast<bool*>(&i);
b |= true; // MAY yield 3 (but doesn’t on my PC!)

그러나이 코드는 어쨌든 정의되지 않은 동작을 초래하므로 C ++ 코드를 준수 할 때이 잠재적 인 문제를 안전하게 무시할 수 있습니다.


1 Angew의 의견에서 알 수 있듯이 이것은 다소 큰 경고입니다.

bool b = true;
b &= 2; // yields `false`.

그 이유는, 즉 b & 2표현식이 다음에 상응되도록 촉진 정수 행하고 static_cast<int>(b) & 2있는 한 결과, 0다음에 다시 변환이다 bool. 따라서의 존재가 operator &&=형식 안전성을 향상시킬 수 있다는 것은 사실입니다 .


4
하지만 &&와 || 연산자는 bool뿐만 아니라 bool 로 변환 되는 모든 작업을 수행합니다 .
dan04

13
bool에서도 똑같은 일을하지 않습니다. ||&&바로 가기는 제 2 인자는 제 피연산자 피연산자가 아닌 경우이고, 즉 true(RESP. false위해 &&). |, &, |=그리고 &=항상 두 피연산자를 평가합니다.
Niki

4
이것은 왜 && = 및 || =가 C ++ 연산자가 아닌지에 대한 질문에 대답하지 않습니다.

9
그건 하지 안전하게 사용할 &=유형의 좌측에 대해 bool우측이 아닌 다른 형식이어야하는 것은 완벽하게 가능하기 때문에, bool(예 islower참값 용 제로하는 리턴 또는 다른 C의 다음 stdlib 작용). 가설이 있다면 &&=우변을로 변환하도록 강제 할 수 bool있지만 &=그렇지 않습니다. 즉, bool b = true; b &= 2;결과는 b == false.
Angew는 더 이상 SO

2
@Antonio 힘든 군중. 😝
Konrad Rudolph

44

&&&다른 의미를 가지고 &&제 오퍼랜드 인 경우 상기 제 피연산자를 평가하지 않을 것이다 false. 즉

flag = (ptr != NULL) && (ptr->member > 3);

안전하지만

flag = (ptr != NULL) & (ptr->member > 3);

두 피연산자가 모두 유형이지만 그렇지 않습니다 bool.

&=및에 대해서도 마찬가지입니다 |=.

flag = CheckFileExists();
flag = flag && CheckFileReadable();
flag = flag && CheckFileContents();

다음과 다르게 동작합니다.

flag = CheckFileExists();
flag &= CheckFileReadable();
flag &= CheckFileContents();

35
내 의견으로는 && =를 가질 더 많은 이유가 있습니다. = P
Kache

4
그러나 이것은 실제로 대답이 아닙니다.
Catskul 19.04.09

27

짧은 답변

모든 사업자는 +=, -=, *=, /=, &=, |=... 산술하고 같은 기대를 제공합니다 :

x &= foo()  // We expect foo() be called whatever the value of x

그러나 연산자 &&=||=는 논리적이며 많은 개발자가 foo()항상 x &&= foo().

bool x;
// ...
x &&= foo();           // Many developers might be confused
x = x && foo();        // Still confusing but correct
x = x ? foo() : x;     // Understandable
x = x ? foo() : false; // Understandable
if (x) x = foo();      // Obvious
  • 바로 가기를 얻기 위해 C / C ++를 더 복잡하게 만들어야 x = x && foo()합니까?

  • 우리는 정말로 비밀스러운 진술을 더 난독 화하고 싶 x = x && foo()습니까?
    아니면 다음과 같은 의미있는 코드를 작성하고 싶 if (x) x = foo();습니까?


긴 대답

&&=

경우 &&=운영자가 가능했던,이 코드 :

bool ok = true; //becomes false when at least a function returns false
ok &&= f1();
ok &&= f2(); //we may expect f2() is called whatever the f1() returned value

다음과 같습니다.

bool ok = true;
if (ok) ok = f1();
if (ok) ok = f2(); //f2() is called only when f1() returns true

이 첫 번째 코드는 많은 개발자 가 항상 반환 된 값이 무엇이든 호출 된다고 생각 하기 때문에 오류가 발생 하기 쉽습니다 . 반환 할 때만 호출 되는 곳에 쓰는 것과 같습니다 .f2()f1()bool ok = f1() && f2();f2()f1()true

  • 개발자가 실제로 f2()f1()반환 할 때만 호출 되기를 원하는 경우 true위의 두 번째 코드는 오류가 덜 발생합니다.
  • 그렇지 않으면 (개발자가 f2()항상 호출 되기를 원함 ) &=충분합니다.

&=

bool ok = true;
ok &= f1();
ok &= f2(); //f2() always called whatever the f1() returned value

또한 컴파일러가 위 코드를 아래 코드보다 최적화하는 것이 더 쉽습니다.

bool ok = true;
if (!f1())  ok = false;
if (!f2())  ok = false;  //f2() always called

비교 &&하고&

우리는 사업자인지 궁금 할 &&하고 &적용 할 때와 동일한 결과를 제공 bool값?

다음 C ++ 코드를 사용하여 확인해 보겠습니다.

#include <iostream>

void test (int testnumber, bool a, bool b)
{
   std::cout << testnumber <<") a="<< a <<" and b="<< b <<"\n"
                "a && b = "<< (a && b)  <<"\n"
                "a &  b = "<< (a &  b)  <<"\n"
                "======================"  "\n";
}

int main ()
{
    test (1, true,  true);
    test (2, true,  false);
    test (3, false, false);
    test (4, false, true);
}

산출:

1) a=1 and b=1
a && b = 1
a &  b = 1
======================
2) a=1 and b=0
a && b = 0
a &  b = 0
======================
3) a=0 and b=0
a && b = 0
a &  b = 0
======================
4) a=0 and b=1
a && b = 0
a &  b = 0
======================

결론

따라서 YES 우리는 대체 할 수있는 &&&에 대한 bool값 ;-)
그래서 더 나은 사용하는 &=대신 &&=. 부울에는 쓸모없는
것으로 간주 할 수 있습니다 &&=.

동일 ||=

오퍼레이터는 |=또한 적은 오류가 발생하기 쉬운 보다||=

개발자가 f2()다음 대신를 f1()반환 할 때만 호출 되기를 원하는 경우 false:

bool ok = false;
ok ||= f1();
ok ||= f2(); //f2() is called only when f1() returns false
ok ||= f3(); //f3() is called only when f1() or f2() return false
ok ||= f4(); //f4() is called only when ...

다음과 같은 더 이해하기 쉬운 대안을 조언합니다.

bool ok = false;
if (!ok) ok = f1();
if (!ok) ok = f2();
if (!ok) ok = f3();
if (!ok) ok = f4();
// no comment required here (code is enough understandable)

또는 모두 한 선 스타일 을 선호하는 경우 :

// this comment is required to explain to developers that 
// f2() is called only when f1() returns false, and so on...
bool ok = f1() || f2() || f3() || f4();

13
이 동작을 실제로 원한다면 어떻게합니까? 왼손 표현이 틀리면 오른손 표현이 실행되지 않습니다. 이 같은 변수를 두 번 작성하는 성가신success = success && DoImportantStuff()
니클라스 R

1
내 조언은 글을 쓰는 것 if(success) success = DoImportantStuff()입니다. 문 success &&= DoImportantStuff()이 허용되면 많은 개발자 DoImportantStuff()는 항상 success. 궁금한 점에 대한 답변이 되었기를 바랍니다. 제 답변의 많은 부분을 개선했습니다. 내 대답이 이제 더 이해하기 쉬운 지 알려주세요. (에 대한 의견 목적) 건배, ;-) 보자
olibre

9
"만약 성명서 success &&= DoImportantStuff()가 허용된다면 많은 개발자들은 DoImportantStuff()항상 성공의 가치가 무엇이든간에 불린다 고 생각할 것 입니다." if (success && DoImportantStuff())그래도 그렇게 말할 수 있습니다 . if 구문의 논리를 기억하는 한 &&=.
pilkch 2014-06-05

2
나는 사람들이 f1()항상에서 평가 한다고 가정하는 방법을 보지 ok &&= f(1) 못하지만 항상에서 평가한다고 가정하지는 않습니다 ok = ok && f(1). 나에게 똑같이 보인다.
einpoklum

1
나는 실제로 변수 v1 및 표현식 e2에 v1 += e2해당하는 구문 설탕이 될 것으로 예상 합니다 v1 = v1 + e1. 약식 표기법이 전부입니다.
einpoklum 2016
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.