นี่เป็นตัวสร้างลักษณะ C ++ เก่าหรือไม่


17

นี่คือโค้ด C ++

ในตัวอย่างนี้บล็อคโค้ดจำนวนมากมีลักษณะเหมือนการเรียกคอนสตรัคเตอร์ น่าเสียดายที่รหัสบล็อก # 3 ไม่ใช่ (คุณสามารถตรวจสอบได้โดยใช้https://godbolt.org/z/q3rsxnและhttps://cppinsights.io )

ฉันคิดว่ามันเป็นสัญกรณ์ C ++ เก่าและสามารถอธิบายการแนะนำของสัญกรณ์การก่อสร้าง C ++ 11 ใหม่โดยใช้ {} (cf # 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)
  }
}

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
Max Langhof

@QuentinUK ขอบคุณสำหรับลิงค์นี้ ฉันรู้เกี่ยวกับฟังก์ชั่น (เช่นT t()) แต่ไม่ใช่สำหรับการประกาศอย่างง่าย เพื่อตรวจสอบว่านี้อาจจะรบกวน
Pascal H.

คำตอบ:


17

คำสั่ง:

T(i);

เทียบเท่ากับ:

T i;

ในคำอื่น ๆ ก็ประกาศชื่อตัวแปรที่มีประเภทi Tนี่เป็นเพราะวงเล็บได้รับอนุญาตในการประกาศในบางสถานที่ (เพื่อเปลี่ยนการเชื่อมโยงของผู้ประกาศ) และเนื่องจากคำสั่งนี้สามารถแยกวิเคราะห์เป็นการประกาศได้ แต่เป็นการประกาศ (แม้ว่ามันอาจจะสมเหตุสมผลมากกว่าในการแสดงออก)


ดังนั้นนี่เป็นเพียงตัวเลือกการตีความที่สืบทอดมาจากข้อกำหนด C ซึ่งจะint(i)ประกาศintชื่อด้วยiหรือไม่
Pascal H.

@PascalH จากมุมมองที่แน่นอนว่าอาจเป็นจริง Stroustrup เขียนใน D&E ว่าเขาได้พิจารณาทางเลือกที่เป็นทางเลือกที่ดีกว่าสำหรับไวยากรณ์ C ++ ถ้า C ++ ไม่จำเป็นต้องย้อนกลับเข้ากันได้กับ C ดังนั้นบางทีมันอาจจะมีไวยากรณ์ทางเลือกและหลีกเลี่ยงความคลุมเครือที่อาจเกิดขึ้นกับนิพจน์
Brian

-1

คุณสามารถใช้Compiler Explorerเพื่อดูว่าเกิดอะไรขึ้นในแอสเซมเบลอร์

คุณสามารถเห็นได้ว่า # 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.