3

고려 : 나는 컴파일러가 접두사와 접미사 사업자에게 전화를 확장하는 방법을 결정하기 위해 실험을했다C++ 컴파일러는 접두사와 접미사 연산자 ++()를 어떻게 확장합니까?

class Example 
{ 
private: 
    int m_i; 

public: 
    Example(int i) : m_i{i} {} 

    //Post-fix 
    Example operator++(int) {m_i++; return *this;} 

    //Pre-fix 
    Example& operator++() {m_i++; return *this;} 

    void print() const {std::cout << m_i << '\n'} 
}; 

.

Example e = 1; 
e++; 
내가 "e.operator ++ (INT)", 또는 한 단계 더 복용 같은 것으로 확대를 예상, 내가

예상

: 나는 이런 식으로 뭔가를 쓰기 예를 들어

,

e++(2); 

"e.operator ++ (2)."와 같이 확장해야하지만 대신 컴파일러에서 " '(Example) (int)'에 대한 호출과 일치하지 않습니다."

다음으로 "++ e"가 "e.operator ++()"로 어떻게 신비하게 확장되어 있는지, 즉 참조를 반환하는 방법에 대해 궁금합니다.

좀 더 주위를 재생, 내가 함께 결국 : 다음 2를 인쇄하고,

Example e = 1; 
++e++; 
e.print(); 

:

3.

내가 이해 인쇄

Example e = 1; 
(++e)++; 
e.print(); 

(++ 전자가)는 객체에 대한 참조를 반환합니다.이 참조는 이후에 1 씩 증가됩니다. 나는 또한 "++ e ++"가 postfix 연산자 우선 순위를 (다른 게시물에서 읽었을 때) 여기에서주고 있다고 생각합니다. 그래서 이것은 postfix 연산자에 의해 리턴 된 임시 변수를 증가시킵니다. 이것 역시 의미가 있습니다. 이로 인해

++++e 
++e++++ 
++++e++ 
++++e++++ 

과 같은 표현식이 어떻게 확장되는지 (모두 컴파일되어 예상 된 결과와 함께 실행 됨) 궁금해졌습니다.

내부에서 도대체 무슨 일이 벌어지고 있고, 컴파일러는 어떤 연산자 ++()를 호출해야하는지, 그리고이 표현식을 어떻게 확장합니까 (특히 접두사의 경우)? "연산자 ++ (int)"에서 자리 표시 자 변수의 용도는 무엇입니까?

+2

자리 표시자는 과부하 해결 중에 두 연산자가 구분되도록 허용하기위한 것입니다. 인수는 지정되지 않았으며 사용되지 않은 상태로 있어야합니다. –

+1

위의 링크를 읽으십시오. 끝에있는 모든 인위적인 예제에는 시퀀스 포인트가 없습니다. – CoryKramer

+1

후위 연산자가 의도대로 동작하도록하려면 다음과 같이 변경하십시오 :'Example operator ++ (int) {return Example (m_i ++); } ' –

답변

2

"연산자 ++ (int)"의 자리 표시 자 변수의 용도는 무엇입니까?

++ 연산자에는 postfix - ++ 및 prefix - ++라는 두 가지 고유 한 기능이 있기 때문입니다. 따라서 오버로드 할 때 두 가지 다른 기능 서명이 있어야합니다. 컴파일러는()를 호출 할 연산자 ++ 알고 않는 방법

,

코드가 ++가 (예 : ++e;) prefix- 사용

, 서명 operator++()와 함수가 호출된다. 코드에서 후위 - ++ (예 : e++;)을 사용하면 서명이 operator++(int) 인 함수가 호출되고 컴파일러에서 지정되지 않은 더미 인수 값을 제공합니다.

기술적으로 operator++(int)의 구현에서는 가명 인수 값을 사용할 수 있습니다.그리고 대신 e.operator++(5);을 쓰면 자신의 가치를 넘어갈 수 있습니다. 하지만 이것은 잘못된 코딩 스타일로 간주 될 것입니다. 연산자를 오버로딩 할 때 사람들이 코드를 읽는 것을 혼란스럽게하지 않도록 기본 제공 연산자의 의미를 유지하는 것이 좋습니다.

현재의 postfix-++ 구현은이 규칙을 따르지 않습니다. 일반적인 의미는 이전 값을 반환해야한다는 것입니다. 그러나 코드는 업데이트 된 값을 반환합니다. 당신이이 구문 분석 규칙에 대해 알아야 할이 문을 구문 분석에 대한

++e++++;

:

    이 일부 단항 ++ e ++ ++; (그리고 의미, 즉
  • 토큰은 "최대 뭉크"에 의해 구문 분석 - + 연산자).
  • 언어 문법은이 토큰에서 표현식이 어떤 연산자의 피연산자인지를 결정합니다. 이 프로세스는 precedence table에 요약 될 수 있습니다.

해당 표를 참조하면 ++(((e++)++))이 표시됩니다. 앞서 언급 확장을 사용하여, 이것은 함수 호출 표기법으로 쓸 수있다 :

((e.operator++(0)).operator++(0)).operator++(); 

이 함수가 호출 될 필요가 왼쪽에서 오른쪽이 경우, 멤버 함수가되고있어 표현하기 전에 입력 할 수 없기 때문에 on이라는 평가가있었습니다.

그래서, 우리는이 문 앞에 Example e(1);했다 가정하면, 다음과 같은 함수 호출이 순서대로 발생합니다

  • e.operator++(int)-e.m_i2에 설정하고 임시 반환에 (나는 의사로 temp1를 호출합니다) temp1.m_i2입니다.
  • temp1.operator++(int)는 - 3temp1.m_i에 설정되고, 그 temp2m.i3
  • temp2.operator++()이다 리턴 - 4temp2.m_i에 설정하고 temp2에 대한 참조를 반환한다.

NB. 내 대답은 멤버 함수 인 오버로드 된 연산자에 대해서만 이야기합니다. 비회원으로 ++ (두 형식 모두)에 과부하를 걸 수도 있습니다. 이 경우 동작은 내 설명과 동일하지만 "함수 호출 표기법"표현식은 다른 구문을 사용합니다.

+0

"++++ e ++"와 같은 것을 확장하는 것은 어떨까요? 나는 postfix가 우선적으로 컴파일러가 (대략적으로) (++ (++ (e ++))와 동등한 것을 볼 것이라는 가정을 잘못하지 않았다고 가정 할 것이다. 이 올바른지? 이것을 실제 함수 호출로 확장하면 e.operator ++ (int) .operator ++(). operator() ++가 될 것입니까? – AldenB

+0

@AldenB 예 맞습니다. –

+0

고마워요, 제가 찾고있는 정확한 응답 유형입니다. – AldenB

관련 문제