과부하 연산자를 사용한 De Morgan의 법칙 최적화
모든 프로그래머는 다음 사항을 알아야합니다.
경우에 따라 프로그램을 최적화하기 위해 컴파일러 (!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||q
에 q||p
뿐만 아니라, x+y
에 y+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
'programing' 카테고리의 다른 글
자바 용 JWT (JSON 웹 토큰) 라이브러리 (0) | 2020.11.11 |
---|---|
D3.js prepend (jQuery prepend와 유사) (0) | 2020.11.11 |
std :: atomic에 대한 잠금은 어디에 있습니까? (0) | 2020.11.11 |
fflush (stdin) 사용 (0) | 2020.11.11 |
.net에서 IEnumerable은 무엇입니까 (0) | 2020.11.11 |