ค่าโสหุ้ยของตัวชี้อัจฉริยะเทียบกับตัวชี้ปกติใน C ++ เป็นเท่าใด


107

ค่าโสหุ้ยของตัวชี้อัจฉริยะเทียบกับพอยน์เตอร์ปกติใน C ++ 11 เป็นเท่าใด กล่าวอีกนัยหนึ่งรหัสของฉันจะช้าลงหรือไม่หากฉันใช้ตัวชี้อัจฉริยะและถ้าเป็นเช่นนั้นจะช้าลงเท่าใด

โดยเฉพาะฉันถามเกี่ยวกับ C ++ 11 std::shared_ptrและstd::unique_ptr.

เห็นได้ชัดว่าสิ่งที่ผลักลงในสแต็กจะมีขนาดใหญ่ขึ้น (อย่างน้อยฉันก็คิดอย่างนั้น) เนื่องจากตัวชี้อัจฉริยะจำเป็นต้องเก็บสถานะภายในไว้ด้วย (จำนวนอ้างอิง ฯลฯ ) คำถามก็คือสิ่งนี้จะเป็นเท่าใด ส่งผลกระทบต่อประสิทธิภาพการทำงานของฉันหรือไม่

ตัวอย่างเช่นฉันส่งคืนตัวชี้อัจฉริยะจากฟังก์ชันแทนที่จะเป็นตัวชี้ปกติ:

std::shared_ptr<const Value> getValue();
// versus
const Value *getValue();

หรือตัวอย่างเช่นเมื่อฟังก์ชันหนึ่งของฉันยอมรับตัวชี้อัจฉริยะเป็นพารามิเตอร์แทนที่จะเป็นตัวชี้ปกติ:

void setValue(std::shared_ptr<const Value> val);
// versus
void setValue(const Value *val);

9
วิธีเดียวที่จะรู้คือการเปรียบเทียบโค้ดของคุณ
Basile Starynkevitch

หมายถึงอันไหน std::unique_ptrหรือstd::shared_ptr?
stefan

11
คำตอบคือ 42 (คำอื่นใครจะรู้คุณต้องกำหนดโปรไฟล์ของคุณและทำความเข้าใจเกี่ยวกับฮาร์ดแวร์ของคุณสำหรับภาระงานทั่วไปของคุณ)
Nim

แอปพลิเคชันของคุณจำเป็นต้องใช้ตัวชี้อัจฉริยะอย่างมากเพื่อให้มีความสำคัญ
user2672165

ค่าใช้จ่ายในการใช้ shared_ptr ในฟังก์ชัน setter แบบง่ายนั้นแย่มากและจะเพิ่มค่าโสหุ้ย 100% หลายรายการ
Lothar

คำตอบ:


185

std::unique_ptr มีค่าใช้จ่ายหน่วยความจำเฉพาะในกรณีที่คุณจัดหา deleter ที่ไม่สำคัญ

std::shared_ptr มีหน่วยความจำเหนือศีรษะสำหรับตัวนับอ้างอิงเสมอแม้ว่าจะมีขนาดเล็กมาก

std::unique_ptr มีเวลาเหนือศีรษะในระหว่างตัวสร้างเท่านั้น (หากต้องคัดลอก deleter ที่ให้มาและ / หรือกำหนดค่าเริ่มต้นของตัวชี้เป็นโมฆะ) และในช่วง destructor (เพื่อทำลายวัตถุที่เป็นเจ้าของ)

std::shared_ptrมีค่าใช้จ่ายด้านเวลาในตัวสร้าง (เพื่อสร้างตัวนับอ้างอิง) ในตัวทำลาย (เพื่อลดตัวนับอ้างอิงและอาจทำลายวัตถุ) และในตัวดำเนินการกำหนด (เพื่อเพิ่มตัวนับอ้างอิง) เนื่องจากการรับประกันความปลอดภัยของเธรดการstd::shared_ptrเพิ่ม / ลดเหล่านี้จึงเป็นแบบปรมาณูดังนั้นการเพิ่มค่าโสหุ้ยเพิ่มเติม

โปรดทราบว่าไม่มีช่วงเวลาใดที่มีค่าใช้จ่ายด้านเวลาในการอ้างอิง (ในการอ้างอิงถึงวัตถุที่เป็นเจ้าของ) ในขณะที่การดำเนินการนี้ดูเหมือนจะเป็นวิธีที่ใช้บ่อยที่สุดสำหรับตัวชี้

สรุปได้ว่ามีค่าใช้จ่ายบางส่วน แต่ไม่ควรทำให้โค้ดช้าเว้นแต่คุณจะสร้างและทำลายตัวชี้อัจฉริยะอย่างต่อเนื่อง


11
unique_ptrไม่มีค่าใช้จ่ายในตัวทำลาย มันทำเช่นเดียวกับที่คุณทำกับตัวชี้ดิบ
R.Martinho Fernandes

6
@ R.MartinhoFernandes เมื่อเปรียบเทียบกับตัวชี้แบบดิบมันมีเวลาเหนือศีรษะในตัวทำลายเนื่องจากตัวทำลายตัวชี้ดิบไม่ทำอะไรเลย เมื่อเปรียบเทียบกับการใช้ตัวชี้แบบดิบแล้วก็ไม่มีค่าใช้จ่ายใด ๆ
lisyarus

3
ที่น่าสังเกตว่าค่าใช้จ่ายในการก่อสร้าง / การทำลาย / การมอบหมายที่ใช้ร่วมกันส่วนหนึ่งเกิดจากความปลอดภัยของเธรด
โจ

1
นอกจากนี้ตัวสร้างเริ่มต้นของstd::unique_ptrอะไร? หากคุณสร้าง a std::unique_ptr<int>ภายในint*จะได้รับการเริ่มต้นnullptrว่าคุณชอบหรือไม่
Martin Drozdik

1
@MartinDrozdik ในสถานการณ์ส่วนใหญ่คุณจะเริ่มต้นตัวชี้ดิบด้วยค่าว่างเพื่อตรวจสอบความว่างเปล่าในภายหลังหรืออะไรทำนองนั้น อย่างไรก็ตามเพิ่มสิ่งนี้ในคำตอบขอบคุณ
lisyarus

29

คำตอบของฉันแตกต่างจากคำตอบอื่น ๆ และฉันสงสัยจริงๆว่าพวกเขาเคยใส่รหัสหรือไม่

shared_ptr มีค่าใช้จ่ายที่สำคัญสำหรับการสร้างเนื่องจากเป็นการจัดสรรหน่วยความจำสำหรับบล็อกควบคุม (ซึ่งเก็บตัวนับการอ้างอิงและรายการตัวชี้ไปยังการอ้างอิงที่อ่อนแอทั้งหมด) นอกจากนี้ยังมีค่าใช้จ่ายหน่วยความจำขนาดใหญ่ด้วยเหตุนี้และความจริงที่ว่า std :: shared_ptr เป็นทูเพิลตัวชี้ 2 ตัวเสมอ (ตัวหนึ่งไปยังวัตถุตัวหนึ่งไปยังบล็อกควบคุม)

หากคุณส่ง shared_pointer ไปยังฟังก์ชันเป็นพารามิเตอร์ค่ามันจะช้าลงอย่างน้อย 10 เท่าจากนั้นจึงเป็นการเรียกแบบปกติและสร้างรหัสจำนวนมากในส่วนรหัสสำหรับการคลายสแต็ก หากคุณผ่านมันโดยการอ้างอิงคุณจะได้รับทิศทางเพิ่มเติมซึ่งอาจแย่ลงในแง่ของประสิทธิภาพ

นั่นเป็นเหตุผลที่คุณไม่ควรทำเช่นนี้เว้นแต่ว่าฟังก์ชันนั้นจะเกี่ยวข้องกับการจัดการความเป็นเจ้าของจริงๆ หรือใช้ "shared_ptr.get ()" ไม่ได้ออกแบบมาเพื่อให้แน่ใจว่าวัตถุของคุณไม่ได้ถูกฆ่าในระหว่างการเรียกใช้ฟังก์ชันปกติ

หากคุณคลั่งไคล้และใช้ shared_ptr กับวัตถุขนาดเล็กเช่นโครงสร้างไวยากรณ์นามธรรมในคอมไพเลอร์หรือบนโหนดเล็ก ๆ ในโครงสร้างกราฟอื่น ๆ คุณจะเห็นการลดลงอย่างมากและหน่วยความจำที่เพิ่มขึ้นอย่างมาก ฉันได้เห็นระบบ parser ซึ่งเขียนใหม่ไม่นานหลังจาก C ++ 14 เข้าสู่ตลาดและก่อนที่โปรแกรมเมอร์จะเรียนรู้การใช้ตัวชี้อัจฉริยะอย่างถูกต้อง การเขียนซ้ำมีขนาดที่ช้ากว่ารหัสเก่า

ไม่ใช่กระสุนเงินและตัวชี้ดิบก็ไม่เลวตามคำจำกัดความเช่นกัน โปรแกรมเมอร์แย่ก็แย่และออกแบบไม่ดีก็แย่ ออกแบบด้วยความระมัดระวังออกแบบโดยคำนึงถึงความเป็นเจ้าของที่ชัดเจนและพยายามใช้ shared_ptr เป็นส่วนใหญ่ในขอบเขต API ของระบบย่อย

หากคุณต้องการเรียนรู้เพิ่มเติมคุณสามารถดู Nicolai M. Josuttis พูดคุยดีๆเกี่ยวกับ "ราคาที่แท้จริงของตัวชี้ที่ใช้ร่วมกันใน C ++" https://vimeo.com/131189627
ซึ่งจะลงลึกในรายละเอียดการใช้งานและสถาปัตยกรรม CPU สำหรับอุปสรรคในการเขียนอะตอม ล็อค ฯลฯ เมื่อฟังคุณจะไม่พูดถึงคุณสมบัตินี้ว่าถูก หากคุณต้องการพิสูจน์ขนาดที่ช้าลงให้ข้าม 48 นาทีแรกและดูเขาเรียกใช้โค้ดตัวอย่างซึ่งทำงานช้ากว่า 180 เท่า (คอมไพล์ด้วย -O3) เมื่อใช้ตัวชี้ที่ใช้ร่วมกันทุกที่


ขอบคุณสำหรับคำตอบ! คุณสร้างโปรไฟล์บนแพลตฟอร์มใด คุณสามารถสำรองข้อมูลการอ้างสิทธิ์ของคุณได้หรือไม่?
Venemo

ฉันไม่มีหมายเลขที่จะแสดง แต่คุณสามารถค้นหาได้ใน Nico Josuttis talk vimeo.com/131189627
Lothar

7
เคยได้ยินstd::make_shared()ไหม? นอกจากนี้ฉันพบว่าการสาธิตการใช้ในทางที่ผิดอย่างโจ่งแจ้งเป็นสิ่งที่ไม่ดีน่าเบื่อเล็กน้อย ...
กำจัดข้อมูลซ้ำซ้อน

2
"make_shared" ที่ทำได้ทั้งหมดจะทำให้คุณปลอดภัยจากการจัดสรรเพิ่มเติมหนึ่งรายการและเพิ่มพื้นที่แคชให้คุณอีกเล็กน้อยหากจัดสรรบล็อกควบคุมไว้ด้านหน้าวัตถุ มันช่วยไม่ได้เลยเมื่อคุณผ่านตัวชี้ไปรอบ ๆ นี่ไม่ใช่ต้นตอของปัญหา
Lothar

26

เช่นเดียวกับประสิทธิภาพของโค้ดทั้งหมดวิธีเดียวที่เชื่อถือได้จริงๆในการรับข้อมูลที่ยากคือการวัดและ / หรือตรวจสอบรหัสเครื่อง

ที่กล่าวว่าเหตุผลง่ายๆบอกอย่างนั้น

  • คุณสามารถคาดหวังค่าใช้จ่ายบางอย่างในการสร้างการดีบักเนื่องจากเช่นoperator->ต้องเรียกใช้งานเป็นการเรียกใช้ฟังก์ชันเพื่อที่คุณจะสามารถก้าวเข้ามาได้ (ในทางกลับกันเนื่องจากขาดการสนับสนุนโดยทั่วไปสำหรับการทำเครื่องหมายคลาสและฟังก์ชันว่าไม่ใช่การดีบัก)

  • สำหรับshared_ptrคุณสามารถคาดหวังค่าใช้จ่ายบางส่วนในการสร้างครั้งแรกเนื่องจากเกี่ยวข้องกับการจัดสรรแบบไดนามิกของบล็อกควบคุมและการจัดสรรแบบไดนามิกจะช้ากว่าการดำเนินการพื้นฐานอื่น ๆ ใน C ++ มาก (ใช้make_sharedเมื่อเป็นไปได้จริงเพื่อลดค่าใช้จ่ายนั้นให้น้อยที่สุด)

  • นอกจากนี้สำหรับshared_ptrมีบางค่าใช้จ่ายในการบำรุงรักษาน้อยที่สุดนับอ้างอิงเช่นเมื่อผ่านshared_ptrโดยค่า unique_ptrแต่ไม่มีค่าใช้จ่ายดังกล่าว

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

คณะกรรมการกำหนดมาตรฐาน C ++ ระหว่างประเทศได้เผยแพร่รายงานทางเทคนิคเกี่ยวกับประสิทธิภาพการทำงาน แต่เป็นในปี 2549 ก่อนหน้านี้unique_ptrและshared_ptrได้รับการเพิ่มลงในไลบรารีมาตรฐาน ถึงกระนั้นพอยน์เตอร์ที่ชาญฉลาดก็เป็นหมวกเก่าในตอนนั้นดังนั้นรายงานจึงพิจารณาเช่นกัน อ้างถึงส่วนที่เกี่ยวข้อง:

“ หากการเข้าถึงค่าผ่านสมาร์ทพอยน์เตอร์เล็กน้อยนั้นช้ากว่าการเข้าถึงผ่านตัวชี้ธรรมดาอย่างมากคอมไพเลอร์จะจัดการกับนามธรรมได้อย่างไม่มีประสิทธิภาพ ในอดีตคอมไพเลอร์ส่วนใหญ่มีบทลงโทษที่เป็นนามธรรมที่สำคัญและคอมไพเลอร์ในปัจจุบันหลายตัวยังคงทำอยู่ อย่างไรก็ตามมีรายงานว่าคอมไพเลอร์อย่างน้อยสองคอมไพเลอร์มีบทลงโทษที่เป็นนามธรรมต่ำกว่า 1% และอีก 3% ดังนั้นการกำจัดค่าใช้จ่ายประเภทนี้จึงอยู่ในขั้นตอนที่ทันสมัย”

ตามการคาดเดาอย่างมีข้อมูล "ภายในที่ทันสมัย" ได้รับความสำเร็จจากคอมไพเลอร์ที่ได้รับความนิยมมากที่สุดในปัจจุบันเมื่อต้นปี 2014


คุณช่วยกรุณาใส่รายละเอียดบางอย่างในคำตอบของคุณเกี่ยวกับกรณีที่ฉันเพิ่มในคำถามของฉันได้ไหม
Venemo

สิ่งนี้อาจเกิดขึ้นจริงเมื่อ 10 ปีก่อน แต่ในปัจจุบันการตรวจสอบรหัสเครื่องไม่ได้มีประโยชน์อย่างที่บุคคลข้างบนแนะนำ ขึ้นอยู่กับว่าคำสั่งเป็นไปป์ไลน์, vectorized, ... และวิธีที่คอมไพลเลอร์ / โปรเซสเซอร์เกี่ยวข้องกับการเก็งกำไรในท้ายที่สุดคือความเร็วเพียงใด รหัสเครื่องรหัสน้อยไม่จำเป็นต้องหมายถึงรหัสที่เร็วขึ้น วิธีเดียวที่จะตรวจสอบประสิทธิภาพคือการกำหนดโปรไฟล์ สิ่งนี้สามารถเปลี่ยนแปลงได้บนพื้นฐานของโปรเซสเซอร์และต่อคอมไพเลอร์
Byron

ปัญหาที่ฉันพบคือเมื่อมีการใช้ shared_ptrs ในเซิร์ฟเวอร์แล้วการใช้งาน shared_ptrs จะเริ่มแพร่หลายและในไม่ช้า shared_ptrs ก็กลายเป็นเทคนิคการจัดการหน่วยความจำเริ่มต้น ตอนนี้คุณมีบทลงโทษที่เป็นนามธรรมซ้ำแล้วซ้ำอีก 1-3% ซึ่งจะถูกนำมาใช้ซ้ำแล้วซ้ำเล่า
Nathan Doromal

ฉันคิดว่าการเปรียบเทียบการสร้างการดีบักนั้นเป็นการเสียเวลาโดยสิ้นเชิง
Paul Childs

14

กล่าวอีกนัยหนึ่งรหัสของฉันจะช้าลงหรือไม่หากฉันใช้ตัวชี้อัจฉริยะและถ้าเป็นเช่นนั้นจะช้าลงเท่าใด

ช้าลง? ไม่น่าจะเป็นไปได้มากนักเว้นแต่คุณจะสร้างดัชนีขนาดใหญ่โดยใช้ shared_ptrs และคุณมีหน่วยความจำไม่เพียงพอจนถึงจุดที่คอมพิวเตอร์ของคุณเริ่มเหี่ยวย่นเช่นหญิงชราที่ถูกดิ่งลงสู่พื้นด้วยแรงที่เหลือทนจากระยะไกล

สิ่งที่จะทำให้โค้ดของคุณช้าลงคือการค้นหาที่เฉื่อยชาการประมวลผลแบบวนซ้ำที่ไม่จำเป็นสำเนาข้อมูลจำนวนมากและการเขียนจำนวนมากลงดิสก์ (เช่นหลายร้อย)

ข้อดีของตัวชี้อัจฉริยะล้วนเกี่ยวข้องกับการจัดการ แต่ค่าใช้จ่ายจำเป็นหรือไม่? ขึ้นอยู่กับการใช้งานของคุณ สมมติว่าคุณกำลังทำซ้ำในอาร์เรย์ 3 เฟสแต่ละเฟสมีอาร์เรย์ 1024 องค์ประกอบ การสร้างไฟล์smart_ptrกระบวนการนี้อาจจะใช้งานได้มากเกินไปเนื่องจากเมื่อทำซ้ำเสร็จแล้วคุณจะรู้ว่าคุณต้องลบมัน คุณจึงสามารถเพิ่มหน่วยความจำได้จากการไม่ใช้ไฟล์smart_ptr ...

แต่คุณต้องการทำอย่างนั้นจริงๆหรือ?

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

ก็เหมือนกับการพูดว่า "ซอฟต์แวร์ของคุณรับประกัน 3 เดือนแล้วโทรหาฉันเพื่อขอรับบริการ"

ในที่สุดมันก็เป็นเรื่องของ ... คุณสามารถจัดการกับความเสี่ยงนี้ได้หรือไม่? การใช้ตัวชี้ดิบเพื่อจัดการการจัดทำดัชนีของคุณในวัตถุต่างๆหลายร้อยชิ้นนั้นคุ้มค่ากับการสูญเสียการควบคุมหน่วยความจำ

ถ้าคำตอบคือใช่ให้ใช้ตัวชี้ดิบ

หากคุณไม่ต้องการพิจารณาด้วยซ้ำ a smart_ptrเป็นวิธีที่ดีใช้งานได้และยอดเยี่ยม


4
โอเค แต่ valgrind นั้นดีในการตรวจสอบการรั่วไหลของหน่วยความจำที่เป็นไปได้ดังนั้นตราบใดที่คุณใช้คุณควรจะปลอดภัย™
graywolf

@Paladin ใช่ถ้าคุณสามารถจัดการกับหน่วยความจำของคุณsmart_ptrจะมีประโยชน์มากสำหรับทีมใหญ่
Claudiordgz

3
ฉันใช้ unique_ptr มันทำให้หลาย ๆ อย่างง่ายขึ้น แต่ไม่ชอบ shared_ptr การนับอ้างอิงนั้นไม่ค่อยมีประสิทธิภาพ GC และมันก็ไม่สมบูรณ์แบบเช่นกัน
graywolf

1
@Paladin ฉันพยายามใช้คำชี้ดิบถ้าฉันสามารถห่อหุ้มทุกอย่างได้ ถ้าเป็นสิ่งที่ฉันจะพูดไปทั่วทุกที่เช่นการโต้เถียงฉันอาจจะพิจารณา smart_ptr unique_ptrs ส่วนใหญ่ของฉันถูกใช้ในการใช้งานขนาดใหญ่เช่น main หรือ run method
Claudiordgz

@Lothar ฉันเห็นคุณถอดความสิ่งหนึ่งที่ฉันพูดในคำตอบของคุณ: Thats why you should not do this unless the function is really involved in ownership management... คำตอบที่ดีขอบคุณโหวต
Claudiordgz

-1

เพียงแวบเดียวและสำหรับตัว[]ดำเนินการมันช้ากว่าตัวชี้ดิบประมาณ 5 เท่าตามที่แสดงในโค้ดต่อไปนี้ซึ่งรวบรวมโดยใช้gcc -lstdc++ -std=c++14 -O0และส่งออกผลลัพธ์นี้:

malloc []:     414252610                                                 
unique []  is: 2062494135                                                
uq get []  is: 238801500                                                 
uq.get()[] is: 1505169542
new is:        241049490 

ฉันกำลังเริ่มเรียนรู้ c ++ ฉันมีสิ่งนี้อยู่ในใจคุณจำเป็นต้องรู้เสมอว่าคุณกำลังทำอะไรอยู่และใช้เวลามากขึ้นเพื่อที่จะรู้ว่าคนอื่นทำอะไรใน c ++ ของคุณ

แก้ไข

ตามที่ปรุงแต่งโดย @ โมฮันกุมารฉันได้ให้รายละเอียดเพิ่มเติม เวอร์ชัน gcc คือ7.4.0 (Ubuntu 7.4.0-1ubuntu1~14.04~ppa1)ผลลัพธ์ข้างต้นได้รับเมื่อ-O0ใช้อย่างไรก็ตามเมื่อฉันใช้แฟล็ก '-O2' ฉันได้รับสิ่งนี้:

malloc []:     223
unique []  is: 105586217
uq get []  is: 71129461
uq.get()[] is: 69246502
new is:        9683

จากนั้นขยับไปclang version 3.9.0, -O0คือ:

malloc []:     409765889
unique []  is: 1351714189
uq get []  is: 256090843
uq.get()[] is: 1026846852
new is:        255421307

-O2 คือ:

malloc []:     150
unique []  is: 124
uq get []  is: 83
uq.get()[] is: 83
new is:        54

ผลของเสียงดังกราว-O2นั้นน่าทึ่งมาก

#include <memory>
#include <iostream>
#include <chrono>
#include <thread>

uint32_t n = 100000000;
void t_m(void){
    auto a  = (char*) malloc(n*sizeof(char));
    for(uint32_t i=0; i<n; i++) a[i] = 'A';
}
void t_u(void){
    auto a = std::unique_ptr<char[]>(new char[n]);
    for(uint32_t i=0; i<n; i++) a[i] = 'A';
}

void t_u2(void){
    auto a = std::unique_ptr<char[]>(new char[n]);
    auto tmp = a.get();
    for(uint32_t i=0; i<n; i++) tmp[i] = 'A';
}
void t_u3(void){
    auto a = std::unique_ptr<char[]>(new char[n]);
    for(uint32_t i=0; i<n; i++) a.get()[i] = 'A';
}
void t_new(void){
    auto a = new char[n];
    for(uint32_t i=0; i<n; i++) a[i] = 'A';
}

int main(){
    auto start = std::chrono::high_resolution_clock::now();
    t_m();
    auto end1 = std::chrono::high_resolution_clock::now();
    t_u();
    auto end2 = std::chrono::high_resolution_clock::now();
    t_u2();
    auto end3 = std::chrono::high_resolution_clock::now();
    t_u3();
    auto end4 = std::chrono::high_resolution_clock::now();
    t_new();
    auto end5 = std::chrono::high_resolution_clock::now();
    std::cout << "malloc []:     " <<  (end1 - start).count() << std::endl;
    std::cout << "unique []  is: " << (end2 - end1).count() << std::endl;
    std::cout << "uq get []  is: " << (end3 - end2).count() << std::endl;
    std::cout << "uq.get()[] is: " << (end4 - end3).count() << std::endl;
    std::cout << "new is:        " << (end5 - end4).count() << std::endl;
}


ตอนนี้ฉันได้ทดสอบโค้ดแล้วมันช้าเพียง 10% เมื่อใช้ตัวชี้ที่ไม่ซ้ำกัน
Mohan Kumar

8
ไม่เคยเปรียบเทียบกับ-O0หรือดีบักโค้ด เอาท์พุทจะไม่มีประสิทธิภาพมาก ใช้อย่างน้อยเสมอ-O2(หรือ-O3ในปัจจุบันเนื่องจากไม่ได้ทำเวกเตอร์บางอย่างใน-O2)
phuclv

1
หากคุณมีเวลาและต้องการพักดื่มกาแฟให้ใช้เวลา -O4 เพื่อรับการเพิ่มประสิทธิภาพเวลาลิงก์และฟังก์ชันนามธรรมเล็ก ๆ น้อย ๆ ทั้งหมดจะอยู่ในบรรทัดและหายไป
Lothar

คุณควรรวมการfreeโทรในการทดสอบ malloc และdelete[]สำหรับใหม่ (หรือทำให้ตัวแปรaคงที่) เนื่องจากunique_ptrs กำลังโทรdelete[]อยู่ภายใต้ประทุนในตัวทำลายของพวกเขา
RnMss
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.