이것은 오래된 C ++ 스타일 생성자입니까?


17

여기에 C ++ 코드가 있습니다.

이 예제에서 많은 코드 블록은 생성자 호출처럼 보입니다. 불행히도, 블록 코드 # 3은 그렇지 않습니다 ( https://godbolt.org/z/q3rsxnhttps://cppinsights.io를 사용하여 확인할 수 있음 ).

필자는 구식 C ++ 표기법이며 {} (cf # 4)를 사용하여 새로운 C ++ 11 구성 표기법의 도입을 설명 할 수 있다고 생각합니다.

T(i)생성자 표기법에 가깝지만 의미가 다른 의미에 대한 설명이 있습니까?

struct T {
   T() { }
   T(int i) { }
};

int main() {
  int i = 42;
  {  // #1
     T t(i);     // new T named t using int ctor
  }
  {  // #2
     T t = T(i); // new T named t using int ctor
  }
  {  // #3
     T(i);       // new T named i using default ctor
  }
  {  // #4
     T{i};       // new T using int ctor (unnamed result)
  }
  {  // #5
     T(2);       // new T using int ctor (unnamed result)
  }
}

NB : 따라서 T(i)(# 3)은 T i = T();


1
나는 당신의 모든 진술이 정확하다고 생각합니다.
Arne J


추가 컴파일러는 그냥 묻는다면 당신이 알아야 할 거의 모든 당신을 말할 것이다 주 -Wall당신이 얻을 " warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'i' [-Wvexing-parse]"그 소리에서, 또는 약간 덜 동기 " warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]" GCC에서 .
맥스 랭 호프

@QuentinUK이 링크에 감사드립니다. 나는 함수 (예 :)에 대해 알고 T t()있었지만 그렇게 단순한 선언 표현식은 아닙니다. 확실히, 이것은 vexing 일 수 있습니다 .
Pascal H.

답변:


17

진술 :

T(i);

다음과 같습니다.

T i;

즉, itype 이라는 이름의 변수를 선언합니다 T. 이는 선언자의 바인딩을 변경하기 위해 일부 위치에서 선언에 괄호를 사용할 수 있고이 명령문을 선언으로 구문 분석 할 수 있으므로 선언입니다 (표현식으로 이해하는 경우에도).


그래서, C 사양에서 상속이 단지 해석의 선택을 int(i)선언도 int라는 이름은 i?
파스칼 H.

@PascalH. 특정 관점에서 보면 그것은 사실 일 수 있습니다. Stroustrup은 D & E에서 C ++에 대한 대안적이고보다 직관적 인 선언 구문을 고려했다고 썼다. C ++가 C와 역 호환되지 않았 으면 대체 구문을 사용하므로 표현식에 대한 모호성을 피할 수 있습니다.
브라이언

-1

컴파일러 탐색기 를 사용 하여 어셈블러에서 어떤 일이 발생하는지 확인할 수 있습니다 .

# 1, # 2 # 4 및 # 5는 동일한 작업을 수행하지만 강하게 # 3은 다른 생성자 (기본 개체 생성자)를 호출합니다.

누구든지 설명이 있습니까?

어셈블러 코드 :

::T() [base object constructor]:
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        nop
        pop     rbp
        ret
T::T(int):
        push    rbp
        mov     rbp, rsp
        mov     QWORD PTR [rbp-8], rdi
        mov     DWORD PTR [rbp-12], esi
        nop
        pop     rbp
        ret
main:
        push    rbp
        mov     rbp, rsp
        sub     rsp, 16
        mov     DWORD PTR [rbp-4], 42
// #1
        mov     edx, DWORD PTR [rbp-4]
        lea     rax, [rbp-7]
        mov     esi, edx
        mov     rdi, rax
        call    T::T(int)
// #2
        mov     edx, DWORD PTR [rbp-4]
        lea     rax, [rbp-8]
        mov     esi, edx
        mov     rdi, rax
        call    T::T(int)
// #3
        lea     rax, [rbp-9]
        mov     rdi, rax
        call    T::T() [complete object constructor]
// #4
        mov     edx, DWORD PTR [rbp-4]
        lea     rax, [rbp-6]
        mov     esi, edx
        mov     rdi, rax
        call    T::T(int)
// #5
        lea     rax, [rbp-5]
        mov     esi, 2
        mov     rdi, rax
        call    T::T(int)

        mov     eax, 0
        leave
        ret

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