programing

과부하 연산자를 사용한 De Morgan의 법칙 최적화

nasanasas 2020. 11. 11. 20:14
반응형

과부하 연산자를 사용한 De Morgan의 법칙 최적화


모든 프로그래머는 다음 사항을 알아야합니다.

드 모건 1
드 모건 2
( 드 모건의 법칙)

경우에 따라 프로그램을 최적화하기 위해 컴파일러 (!p && !q)(!(p || q)).

두 표현식은 동일하며 첫 번째 또는 두 번째를 평가하는 데 차이가 없습니다.
그러나 C ++에서는 연산자를 오버로드 할 수 있으며 오버로드 된 연산자가 항상이 속성을 존중하는 것은 아닙니다. 따라서 이러한 방식으로 코드를 변환하면 실제로 코드가 수정됩니다.

컴파일러 !, ||&&과부하 시 De Morgan의 법칙을 사용해야 합니까?


참고 :

내장 연산자 && 및 || 단락 평가를 수행 하지만 (첫 번째 평가 후 결과가 알려진 경우 두 번째 피연산자를 평가하지 않음) 오버로드 된 연산자는 일반 함수 호출처럼 작동 하고 항상 두 피연산자를 모두 평가합니다 .

... operator && 및 operator ||의 단락 특성 때문에 오버로드에는 적용하지 마십시오. 부울 의미가있는 유형은 일반적이지 않기 때문에 두 개의 표준 라이브러리 클래스 만 이러한 연산자를 오버로드합니다.

출처 : http://en.cppreference.com/w/cpp/language/operator_logical (emphasis mine)

그리고 그 :

내장 후보 연산자 함수와 동일한 이름 및 매개 변수 유형을 가진 사용자 작성 후보가있는 경우 내장 연산자 함수가 숨겨 지고 후보 함수 세트에 포함되지 않습니다.

출처 : n4431 13.6 내장 연산자 [over.built] (강조 광산)

요약하면 오버로드 된 연산자는 일반 사용자 작성 함수처럼 작동합니다.

아니요, 컴파일러는 사용자 작성 함수 호출을 다른 사용자 작성 함수 호출로 대체하지 않습니다. 그렇지 않으면 잠재적으로 "as if" 규칙을 위반할 수 있습니다.


나는 당신이 당신 자신의 질문에 대답했다고 생각합니다. 아니오, 컴파일러는 이것을 할 수 없습니다. 연산자는 오버로드 될 수있을뿐만 아니라 일부는 정의조차 할 수 없습니다. 예를 들어, 가질 수 operator &&있고 operator !정의 할 수 있지만 operator ||전혀 정의하지 않을 수 있습니다 .

컴파일러가 따를 수없는 다른 많은 법칙이 있습니다. 예를 들어, 변경할 수 없습니다 p||qq||p뿐만 아니라, x+yy+x.

(위의 모든 것은 질문이 요구하는 것이므로 오버로드 된 연산자에 적용됩니다.)


아니요,이 경우 변환은 유효하지 않습니다. 변환 할 수있는 권한 !p && !q으로는 !(p || q)대로의 경우 규칙에 의해, 암시 적이다. as-if 규칙은 대략적으로 말하면 올바른 프로그램으로 관찰 할 수없는 모든 변환을 허용합니다. 오버로드 된 연산자가 사용되고 변환을 감지하면 자동으로 변환이 더 이상 허용되지 않음을 의미합니다.


오버로딩 된 연산자 는 그 자체 로 함수 호출을위한 문법적 설탕 일뿐입니다 . 컴파일러 자체는 그러한 호출에 대해 보유하거나 보유하지 않을 수있는 속성에 대해 어떠한 가정도 할 수 없습니다. 특정 연산자의 속성을 활용하는 최적화 (예 : 부울 연산자에 대한 De Morgan, 합계에 대한 교환 성, 합계 / 제품에 대한 분포, 적절한 곱셈에서 적분 나누기의 변환 등)는 "실제 연산자"가있는 경우에만 사용할 수 있습니다. 사용됩니다.

대신 표준 라이브러리의 일부는 특정 의미 론적 의미를 오버로드 된 연산자와 연관시킬 수 있습니다. 예를 들어 std::sort기본적으로 operator<요소 간의 엄격한 약한 순서를 준수하는를 기대 하지만 이는 물론 각 알고리즘의 전제 조건에 나열되어 있습니다. 컨테이너.

(덧붙여 말하자면, 과부하 &&및 것은 ||그들이 자신의 행동이 놀라운 따라서 잠재적으로 위험한가되도록, 과부하 자신의 단락 속성을 잃게하기 때문에 어차피 피해야한다)


컴파일러가 프로그램을 임의로 다시 작성하여 작성하지 않은 작업을 수행 할 수 있는지 묻습니다.

대답은 : 당연하지의!

  • De Morgan의 법률이 적용되는 경우 적용될 수 있습니다.
  • 그렇지 않은 경우에는 그렇지 않을 수 있습니다.

정말 간단합니다.


직접적으로는 아닙니다.

p와 q가 표현식이므로 p에 오버로드 된 연산자가 없으면 단락 평가가 적용됩니다. 표현식 q는 p가 거짓 인 경우에만 평가됩니다.

p가 원시 유형이 아닌 경우 단락 평가가 없으며 과부하 된 기능은 기존 사용과 관련이 없더라도 무엇이든 될 수 있습니다.

컴파일러는 자체적으로 최적화를 수행합니다. 아마도 그것은 de Morgan의 정체성을 초래할 수 있지만 if 조건 교체 수준은 아닙니다.


DeMorgan의 법칙 은 이러한 연산자 의미적용됩니다 . 오버로딩 은 해당 연산자 구문적용됩니다 . 오버로드 된 연산자가 DeMorgan의 법칙을 적용하는 데 필요한 의미를 구현한다는 보장은 없습니다.


그러나 C ++에서는 연산자를 오버로드 할 수 있으며 오버로드 된 연산자가 항상이 속성을 존중하는 것은 아닙니다.

오버로드 된 연산자는 더 이상 연산자가 아니라 함수 호출입니다.

class Boolean
{
  bool value;

  ..

  Boolean operator||(const Boolean& b)
  {
      Boolean c;
      c.value = this->value || b.value;
      return c;
  }

  Boolean logical_or(const Boolean& b)
  {
      Boolean c;
      c.value = this->value || b.value;
      return c;
  }
}

그래서이 코드 줄은

Boolean a (true);
Boolean b (false);

Boolean c = a || b;

이것과 같다

Boolean c = a.logical_or(b);

참고 URL : https://stackoverflow.com/questions/33120453/de-morgans-law-optimization-with-overloaded-operators

반응형