ฉันจะไม่กังวลเกี่ยวกับมัน หากคุณทำแบบวนซ้ำสตริงจะจัดสรรหน่วยความจำล่วงหน้าเสมอเพื่อลดการจัดสรรใหม่ - เพียงใช้operator+=
ในกรณีนั้น และถ้าคุณทำด้วยตนเองสิ่งนี้หรือนานกว่านั้น
a + " : " + c
จากนั้นเป็นการสร้าง Temporaries แม้ว่าคอมไพเลอร์จะสามารถกำจัดสำเนาค่าส่งคืนบางส่วนได้ นั่นเป็นเพราะในการเรียกแบบต่อเนื่องoperator+
ไม่ทราบว่าพารามิเตอร์อ้างอิงอ้างอิงอ็อบเจ็กต์ที่มีชื่อหรือส่งคืนชั่วคราวจากการoperator+
เรียกใช้ย่อย ฉันไม่ควรกังวลเกี่ยวกับเรื่องนี้ก่อนที่จะไม่ได้ทำโปรไฟล์ก่อน แต่ลองมาเป็นตัวอย่างเพื่อแสดงให้เห็นว่า อันดับแรกเราแนะนำวงเล็บเพื่อให้การเชื่อมโยงชัดเจน ฉันใส่อาร์กิวเมนต์โดยตรงหลังจากการประกาศฟังก์ชันที่ใช้เพื่อความชัดเจน ด้านล่างนี้ฉันจะแสดงว่านิพจน์ผลลัพธ์คืออะไร:
((a + " : ") + c)
calls string operator+(string const&, char const*)(a, " : ")
=> (tmp1 + c)
ตอนนี้นอกเหนือจากนั้นtmp1
คือสิ่งที่ส่งกลับมาจากการเรียกตัวดำเนินการครั้งแรก + พร้อมด้วยอาร์กิวเมนต์ที่แสดง เราถือว่าคอมไพเลอร์ฉลาดมากและปรับสำเนาค่าส่งคืนให้เหมาะสม ดังนั้นเราจึงจบลงด้วยสตริงใหม่หนึ่งที่มีการเรียงต่อกันของและa
" : "
ตอนนี้สิ่งนี้เกิดขึ้น:
(tmp1 + c)
calls string operator+(string const&, string const&)(tmp1, c)
=> tmp2 == <end result>
เปรียบเทียบกับสิ่งต่อไปนี้:
std::string f = "hello";
(f + c)
calls string operator+(string const&, string const&)(f, c)
=> tmp1 == <end result>
มันใช้ฟังก์ชันเดียวกันสำหรับสตริงชั่วคราวและสตริงที่มีชื่อ! ดังนั้นคอมไพเลอร์จึงต้องคัดลอกอาร์กิวเมนต์ไปยังสตริงใหม่และต่อท้ายและส่งคืนจากเนื้อหาของoperator+
. ไม่สามารถใช้หน่วยความจำชั่วคราวและผนวกเข้ากับสิ่งนั้นได้ ยิ่งนิพจน์ใหญ่เท่าไหร่ก็ยิ่งต้องทำสำเนาสตริงมากขึ้นเท่านั้น
Visual Studio และ GCC ถัดไปจะรองรับความหมายการเคลื่อนที่ของ c ++ 1x (การเสริมความหมายของการคัดลอก ) และการอ้างอิงค่า rvalue เป็นการเพิ่มการทดลอง ซึ่งช่วยให้ทราบว่าพารามิเตอร์อ้างถึงชั่วคราวหรือไม่ สิ่งนี้จะทำให้การเพิ่มดังกล่าวรวดเร็วอย่างน่าอัศจรรย์เนื่องจากสิ่งที่กล่าวมาทั้งหมดจะจบลงใน "add-pipeline" อันเดียวโดยไม่มีสำเนา
หากกลายเป็นคอขวดคุณยังสามารถทำได้
std::string(a).append(" : ").append(c) ...
การappend
โทรต่อท้ายอาร์กิวเมนต์*this
และส่งคืนการอ้างอิงถึงตัวเอง ดังนั้นจึงไม่มีการคัดลอกชั่วคราว หรืออีกวิธีหนึ่งคือoperator+=
สามารถใช้ได้ แต่คุณจะต้องมีวงเล็บที่น่าเกลียดเพื่อแก้ไขลำดับความสำคัญ