Це старий конструктор стилю C ++?


17

Ось фрагмент коду С ++.

У цьому прикладі багато блоків коду виглядають як виклики конструктора. На жаль, блокового коду №3 немає (Ви можете перевірити це за допомогою https://godbolt.org/z/q3rsxn та https://cppinsights.io ).

Я думаю, що це стара позначка C ++, і це могло б пояснити введення нової нотації конструкції C ++ 11 за допомогою {} (пор. №4).

Чи є у вас пояснення 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)
  }
}

Примітка: таким чином, 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()), але не для таких простих виразів декларації. Напевно, це може бути неприємно .
Паскаль Х.

Відповіді:


17

Заява:

T(i);

еквівалентно:

T i;

Іншими словами, він оголошує змінну, названу iтипом T. Це тому, що в деклараціях дозволено декларування в деяких місцях (щоб змінити прив'язку деклараторів), і оскільки це твердження може бути проаналізовано як декларація, воно є декларацією (хоча це може мати більше сенсу як вираз).


Отже, це лише вибір інтерпретації, успадкований із специфікацій C, де int(i)також оголошується intназваний i?
Паскаль Х.

@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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.