มันละเอียดอ่อนกว่าคำตอบอื่น ๆ ที่แนะนำ ไม่มีการแบ่งสัมบูรณ์ระหว่างข้อมูลบนสแตกและข้อมูลบนฮีปตามวิธีที่คุณประกาศ ตัวอย่างเช่น:
std::vector<int> v(10);
ในเนื้อความของฟังก์ชันที่ประกาศvector
(อาร์เรย์แบบไดนามิก) จำนวนเต็มสิบจำนวนบนสแต็ก แต่หน่วยเก็บข้อมูลที่จัดการโดยvector
ไม่ได้อยู่ในสแต็ก
อ่า แต่ (คำตอบอื่น ๆ แนะนำ) อายุการใช้งานของที่เก็บข้อมูลนั้นถูก จำกัด ด้วยอายุการใช้งานของvector
ตัวมันเองซึ่งต่อไปนี้เป็นแบบสแต็กดังนั้นจึงไม่มีความแตกต่างในการใช้งาน - เราสามารถถือว่าเป็นวัตถุที่ใช้สแต็กเท่านั้น ด้วยอรรถศาสตร์เชิงคุณค่า
ไม่เป็นเช่นนั้น สมมติว่าฟังก์ชันคือ:
void GetSomeNumbers(std::vector<int> &result)
{
std::vector<int> v(10);
// fill v with numbers
result.swap(v);
}
ดังนั้นทุกสิ่งที่มีswap
ฟังก์ชัน (และประเภทค่าที่ซับซ้อนควรมีอย่างใดอย่างหนึ่ง) สามารถทำหน้าที่เป็นชนิดของการอ้างอิงแบบ rebindable ไปยังข้อมูลฮีปบางส่วนภายใต้ระบบที่รับรองว่ามีเจ้าของข้อมูลนั้นเพียงคนเดียว
ดังนั้นแนวทาง C ++ สมัยใหม่จึงไม่ควรทำเก็บที่อยู่ของข้อมูลฮีปในตัวแปรตัวชี้ภายในแบบเปล่า การจัดสรรฮีปทั้งหมดต้องซ่อนอยู่ภายในคลาส
หากคุณทำเช่นนั้นคุณสามารถนึกถึงตัวแปรทั้งหมดในโปรแกรมของคุณราวกับว่าเป็นประเภทค่าที่เรียบง่ายและลืมเกี่ยวกับฮีปไปเลย (ยกเว้นเมื่อเขียนคลาส Wrapper ที่เหมือนค่าใหม่สำหรับข้อมูลฮีปบางอย่างซึ่งน่าจะผิดปกติ) .
คุณเพียงแค่ต้องเก็บความรู้พิเศษไว้อย่างหนึ่งเพื่อช่วยให้คุณเพิ่มประสิทธิภาพ: ถ้าเป็นไปได้แทนที่จะกำหนดตัวแปรหนึ่งให้กับตัวแปรอื่นเช่นนี้
a = b;
เปลี่ยนเป็นแบบนี้:
a.swap(b);
เพราะเร็วกว่ามากและไม่มีข้อยกเว้น ข้อกำหนดเพียงอย่างเดียวคือคุณไม่จำเป็นต้องb
ถือค่าเดิมต่อไป (มันจะได้รับa
ค่าแทนซึ่งจะถูกทิ้งในถังขยะa = b
)
ข้อเสียคือวิธีนี้บังคับให้คุณส่งคืนค่าจากฟังก์ชันผ่านพารามิเตอร์เอาต์พุตแทนที่จะเป็นค่าส่งคืนจริง แต่พวกเขากำลังแก้ไขว่าใน C ++ 0x กับการอ้างอิง rvalue
ในสถานการณ์ที่ซับซ้อนที่สุดคุณจะต้องใช้ความคิดนี้ไปสู่จุดสูงสุดทั่วไปและใช้คลาสตัวชี้อัจฉริยะเช่นshared_ptr
ที่มีอยู่แล้วใน tr1 (แม้ว่าฉันจะเถียงว่าถ้าคุณต้องการมันคุณอาจย้ายไปอยู่นอกจุดที่น่าสนใจของ Standard C ++)