ความแตกต่างระหว่าง alloctaor :: construct ที่เก่ากว่าและตัวสร้างใหม่และตัวสร้างที่ชัดเจนคืออะไร


15

ฉันรู้ว่าstd::allocator<T>::constructใช้พารามิเตอร์เพียงสองตัวใน C ++ รุ่นเก่ากว่า; ตัวแรกคือตัวชี้ไปยังหน่วยความจำที่ไม่ได้สร้างขึ้นซึ่งเราต้องการสร้างวัตถุประเภทTและอันที่สองคือค่าของประเภทองค์ประกอบเพื่อเริ่มต้นวัตถุนั้น ดังนั้นตัวสร้างตัวสร้างจึงถูกเรียกใช้:

struct Foo {
    Foo(int, int) { cout << "Foo(int, int)" << endl; }
    /*explicit*/ Foo(int) { cout << "Foo(int)" << endl; }
    Foo(const Foo&) { cout << "Foo(const Foo&)" << endl; }
};

int main(int argc, char* argv[]) {


    allocator<Foo> a;
    Foo* const p = a.allocate(200, NULL); // second parameter is required on C++98 but on C++11 it is optional
//  Foo* const p = a.allocate(200); // works fine on C++11 but not on C++98

    a.construct(p, 5, 7); // works on C++ 11 and up but not C++98
    a.construct(p, 10);// works on both
    a.destroy(p);
    a.destroy(p + 1);
    a.deallocate(p, 200);



    std::cout << std::endl;
}
  • ทำไมใน C ++ 98 a.construct(p, 10)เรียกตัวสร้างสำเนา แต่ใน C ++ 11 ขึ้นไปกำลังเรียกเพียงตัวสร้างที่ใช้จำนวนเต็ม?

  • สิ่งนี้หมายความว่าใน C ++ 11 เนื่องจากการเพิ่มประสิทธิภาพการคัดลอกบางส่วนแม้ว่าตัวสร้างFoo(int)จะexplicitทำงานในการโทรดังกล่าว: a.construct(p, 5)ทำงานบน C ++ 11 แม้ตัวสร้างคือexplicitสิ่งที่ฉันแน่ใจว่ามันไม่ทำงานบน C ++ 98 ถ้าเป็นFoo(int)explicit

  • ถ้าเป็นเช่นนั้นถ้าฉันรวบรวมคำสั่งที่มีการcopy-elisionเพิ่มประสิทธิภาพการปิดการใช้งานบางประเภทจะทำให้คอมไพเลอร์ล้มเหลว? ขอบคุณ.


3
คำตอบสั้น: จนกว่า C ++ 11 ไม่มีfowarding ที่สมบูรณ์แบบ รายละเอียดให้ด้านล่างโดย @flyx โปรดทราบว่าไม่มีส่วนเกี่ยวข้องในการคัดลอก (ไม่มีการส่งต่อค่าหรือคืนค่า)
Daniel Langr

คำตอบ:


13

นี่เป็นเพราะการประกาศการconstruct เปลี่ยนแปลงใน C ++ 11 :

void construct( pointer p, const_reference val );  (1)  (until C++11)
template< class U, class... Args >
void construct( U* p, Args&&... args );            (2)  (since C++11)

การประกาศครั้งแรกเรียกตัวสร้างการคัดลอกในขณะที่การประกาศครั้งที่สองเรียกตัวสร้างที่ตรงกับรายการของอาร์กิวเมนต์ที่กำหนด นี่อาจเป็นตัวสร้างการคัดลอก แต่ก็เป็นตัวสร้างอื่นตามที่คุณเห็นในรหัสของคุณ

a.construct(p, 10)เรียกใช้ตัวสร้างการคัดลอกใน C ++ 98 เนื่องจาก10มีการแปลงโดยนัยFooผ่านทางตัวFoo(int)สร้าง การแปลงนี้ไม่จำเป็นใน C ++ 11 เนื่องจากมีตัวสร้างที่ตรงกันที่ใช้int(ตัวสร้างที่ใช้สำหรับการแปลงใน C ++ 98) และนี่ก็เป็นเหตุผลว่าทำไมรหัสไม่ได้ทำงานใน C ++ 98 เมื่อคุณเพิ่มexplicit- มันไม่สามารถแปลง10ไปFooแล้ว

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.