È un vecchio costruttore in stile C ++?


17

Qui un pezzo di codice C ++.

In questo esempio, molti blocchi di codice sembrano chiamate del costruttore. Sfortunatamente, il codice di blocco n. 3 non lo è (puoi verificarlo usando https://godbolt.org/z/q3rsxn e https://cppinsights.io ).

Penso che sia una vecchia notazione C ++ e potrebbe spiegare l'introduzione della nuova notazione di costruzione C ++ 11 usando {} (cfr. N. 4).

Hai una spiegazione del T(i)significato, così vicina a una notazione del costruttore, ma decisamente così diversa?

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: quindi, T(i)(# 3) è equivalente a T i = T();


1
Penso che tutte le tue dichiarazioni siano corrette.
Arne J,


Nota che il compilatore ti dirà praticamente tutto ciò che devi sapere se lo chiedi semplicemente: Aggiungi -Walle ottieni " warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'i' [-Wvexing-parse]" da clang, o il " warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]" leggermente meno motivato " da gcc .
Max Langhof,

@QuentinUK grazie per questo link. Ne ero consapevole delle funzioni (ad es. T t()) Ma non per espressioni di dichiarazione così semplici. Di sicuro, questo potrebbe essere irritante .
Pascal H.

Risposte:


17

La dichiarazione:

T(i);

è equivalente a:

T i;

In altre parole, dichiara una variabile denominata icon type T. Questo perché le parentesi sono consentite nelle dichiarazioni in alcuni punti (per cambiare l'associazione dei dichiaranti) e poiché questa affermazione può essere analizzata come una dichiarazione, è una dichiarazione (anche se potrebbe avere più senso come espressione).


Quindi, questa è solo una scelta interpretativa ereditata dalle specifiche C dove int(i)dichiara anche un intnome i?
Pascal H.

@PascalH. Da un certo punto di vista, potrebbe essere vero. Stroustrup ha scritto in D&E di aver considerato una sintassi di dichiarazione alternativa e più intuitiva per C ++. Se C ++ non avesse dovuto essere retrocompatibile con C, allora forse avrebbe avuto una sintassi alternativa, evitando così la potenziale ambiguità con le espressioni.
Brian,

-1

È possibile utilizzare Explorer compilatore per vedere cosa succede nell'assemblatore.

Puoi vedere che # 1, # 2 # 4 e # 5 fanno la stessa cosa ma stranamente # 3 chiamano l'altro costruttore (il costruttore di oggetti base).

Qualcuno ha una spiegazione?

Codice assemblatore:

::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
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.