Est-ce un ancien constructeur de style C ++?

17

Voici un morceau de code C ++.

Dans cet exemple, de nombreux blocs de code ressemblent à des appels de constructeur. Malheureusement, le code de blocage # 3 ne l'est pas (vous pouvez le vérifier en utilisant https://godbolt.org/z/q3rsxn et https://cppinsights.io ).

Je pense que c'est une ancienne notation C ++ et cela pourrait expliquer l'introduction de la nouvelle notation de construction C ++ 11 en utilisant {} (cf # 4).

Avez-vous une explication du T(i)sens, si proche d'une notation constructeur, mais certainement si différente?

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: ainsi T(i)(# 3) est équivalent à T i = T();

Pascal H.
la source
1
Je pense que toutes vos déclarations sont correctes.
Arne J
Notez que le compilateur vous dira à peu près tout ce que vous devez savoir si vous le demandez: ajoutez -Wallet vous obtenez " warning: parentheses were disambiguated as redundant parentheses around declaration of variable named 'i' [-Wvexing-parse]" de clang, ou le "moins motivé warning: unnecessary parentheses in declaration of 'i' [-Wparentheses]" de gcc .
Max Langhof
@QuentinUK merci pour ce lien. J'étais au courant des fonctions (par exemple T t()) mais pas des expressions de déclaration si simples. Pour sûr, cela pourrait être vexant .
Pascal H.

Réponses:

17

La déclaration:

T(i);

est équivalent à:

T i;

En d'autres termes, il déclare une variable nommée iavec type T. En effet, les parenthèses sont autorisées dans les déclarations à certains endroits (afin de modifier la liaison des déclarants) et puisque cette instruction peut être analysée comme une déclaration, il s'agit d'une déclaration (même si elle peut avoir plus de sens en tant qu'expression).

Brian
la source
Alors, est-ce seulement un choix d'interprétation hérité des spécifications C où int(i)déclare également un intnommé i?
Pascal H.
@PascalH. D'un certain point de vue, cela pourrait être vrai. Stroustrup a écrit dans D&E qu'il avait envisagé une syntaxe de déclaration alternative et plus intuitive pour C ++. Si C ++ n'avait pas dû être rétrocompatible avec C, alors il aurait peut-être la syntaxe alternative, et éviterait ainsi l'ambiguïté potentielle avec les expressions.
Brian
-1

Vous pouvez utiliser l' Explorateur de compilateur pour voir ce qui se passe dans l'assembleur.

Vous pouvez voir que # 1, # 2 # 4 et # 5 font la même chose mais étrangement # 3 appelle l'autre constructeur (le constructeur de l'objet de base).

Est-ce que quelqu'un a une explication?

Code assembleur:

::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
Matthieu H
la source