ด้วยภาษา C ++ 17 , shared_ptr
สามารถนำมาใช้ในการจัดการอาร์เรย์จัดสรร shared_ptr
อาร์กิวเมนต์แม่แบบในกรณีนี้จะต้องเป็นหรือT[N]
T[]
ดังนั้นคุณอาจเขียน
shared_ptr<int[]> sp(new int[10]);
จาก n4659, [util.smartptr.shared.const]
template<class Y> explicit shared_ptr(Y* p);
ต้องการ: Y
จะเป็นประเภทที่สมบูรณ์ การแสดงออกdelete[] p
เมื่อT
เป็นประเภทอาร์เรย์หรือdelete p
เมื่อT
ไม่ได้เป็นประเภทอาร์เรย์จะต้องมีพฤติกรรมที่กำหนดไว้อย่างดีและจะไม่โยนข้อยกเว้น
...
ข้อสังเกต:เมื่อT
เป็นประเภทอาร์เรย์คอนสตรัคนี้จะได้มีส่วนร่วมในการแก้ปัญหาเกินเว้นแต่การแสดงออกdelete[] p
เป็นรูปแบบที่ดีและทั้งT
เป็นU[N]
และY(*)[N]
เป็นแปลงสภาพให้แก่T*
หรือT
เป็น
U[]
และเป็นแปลงสภาพให้แก่Y(*)[]
T*
...
เพื่อรองรับสิ่งนี้ประเภทสมาชิกelement_type
จะถูกกำหนดเป็น
using element_type = remove_extent_t<T>;
องค์ประกอบอาร์เรย์สามารถเข้าถึงได้โดยใช้ operator[]
element_type& operator[](ptrdiff_t i) const;
get() != 0 && i >= 0
ต้องใช้: ถ้าT
เป็นU[N]
, i < N
. ...
ข้อสังเกต:เมื่อT
ไม่ได้เป็นประเภทอาเรย์มันจะไม่ได้ระบุว่าฟังก์ชั่นสมาชิกนี้จะมีการประกาศ ถ้ามันถูกประกาศมันจะไม่ระบุว่าประเภทการคืนของมันคืออะไรยกเว้นว่าการประกาศ (แม้ว่าไม่จำเป็นต้องนิยาม) ของฟังก์ชั่นจะต้องมีรูปแบบที่ดี
ก่อนที่จะมี C ++ 17 , shared_ptr
อาจจะไม่ได้ถูกนำมาใช้ในการจัดการอาร์เรย์จัดสรร โดยค่าเริ่มต้นshared_ptr
จะเรียกdelete
วัตถุที่มีการจัดการเมื่อไม่มีการอ้างอิงอีกต่อไป อย่างไรก็ตามเมื่อคุณจัดสรรโดยใช้new[]
คุณต้องโทรdelete[]
และไม่delete
ให้เป็นอิสระจากทรัพยากร
เพื่อที่จะใช้shared_ptr
กับอาร์เรย์ได้อย่างถูกต้องคุณต้องกำหนด deleter ที่กำหนดเอง
template< typename T >
struct array_deleter
{
void operator ()( T const * p)
{
delete[] p;
}
};
สร้าง shared_ptr ดังนี้:
std::shared_ptr<int> sp(new int[10], array_deleter<int>());
ตอนนี้shared_ptr
จะเรียกอย่างถูกต้องdelete[]
เมื่อทำลายวัตถุที่มีการจัดการ
deleter ที่กำหนดเองด้านบนอาจถูกแทนที่ด้วย
std::default_delete
เชี่ยวชาญบางส่วนสำหรับประเภทอาร์เรย์
std::shared_ptr<int> sp(new int[10], std::default_delete<int[]>());
การแสดงออกแลมบ์ดา
std::shared_ptr<int> sp(new int[10], [](int *p) { delete[] p; });
นอกจากนี้หากคุณต้องการใช้งานร่วมกันจริงกับวัตถุที่มีการจัดการ a unique_ptr
เหมาะกว่าสำหรับงานนี้เนื่องจากมีความเชี่ยวชาญบางส่วนสำหรับประเภทอาร์เรย์
std::unique_ptr<int[]> up(new int[10]); // this will correctly call delete[]
การเปลี่ยนแปลงที่แนะนำโดย C ++ Extensions สำหรับ Library Fundamentals
pre-C ++ 17 ทางเลือกอื่น ๆ ที่ระบุไว้ข้างต้นได้รับการจัดทำโดยข้อกำหนดพื้นฐานทางเทคนิคของLibrary Fundamentalsซึ่งเพิ่มขึ้นshared_ptr
เพื่อให้สามารถทำงานนอกกรอบสำหรับกรณีต่างๆเมื่อเป็นเจ้าของอาร์เรย์ของวัตถุ ร่างปัจจุบันของshared_ptr
การเปลี่ยนแปลงที่กำหนดไว้สำหรับการ TS นี้สามารถพบได้ในN4082 การเปลี่ยนแปลงเหล่านี้จะสามารถเข้าถึงได้ผ่านstd::experimental
namespace และรวมอยู่ใน<experimental/memory>
ส่วนหัว การเปลี่ยนแปลงที่เกี่ยวข้องบางประการเพื่อสนับสนุนshared_ptr
อาร์เรย์คือ:
- คำจำกัดความของการelement_type
เปลี่ยนแปลงประเภทสมาชิก
typedef T element_type;
typedef typename remove_extent<T>::type element_type;
- operator[]
กำลังเพิ่มสมาชิก
element_type& operator[](ptrdiff_t i) const noexcept;
- ไม่เหมือนกับunique_ptr
ความเชี่ยวชาญเฉพาะบางส่วนสำหรับอาร์เรย์ทั้งสองshared_ptr<T[]>
และshared_ptr<T[N]>
จะใช้ได้และทั้งคู่จะส่งผลให้delete[]
ถูกเรียกใช้บนอาร์เรย์ของวัตถุที่มีการจัดการ
template<class Y> explicit shared_ptr(Y* p);
ต้องการ : Y
จะเป็นประเภทที่สมบูรณ์ การแสดงออกdelete[] p
เมื่อT
เป็นประเภทอาร์เรย์หรือdelete p
เมื่อT
ไม่ได้เป็นประเภทอาร์เรย์จะต้องมีรูปแบบที่ดีจะต้องมีพฤติกรรมที่กำหนดไว้อย่างดีและจะไม่โยนข้อยกเว้น เมื่อT
เป็นU[N]
, Y(*)[N]
จะต้องแปลงสภาพให้แก่T*
; เมื่อT
เป็นU[]
, Y(*)[]
จะต้องแปลงสภาพให้แก่T*
; มิฉะนั้นจะต้องแปลงสภาพให้แก่Y*
T*
std::vector
คุณยังอาจพิจารณาเพียงแค่ใช้ คุณจะต้องระมัดระวังในการส่งอาเรย์โดยใช้การอ้างอิงเพื่อที่คุณจะไม่ได้ทำสำเนา ไวยากรณ์สำหรับการเข้าถึงข้อมูลนั้นสะอาดกว่า shared_ptr และการปรับขนาดมันง่ายมาก และคุณจะได้รับความดี STL ทั้งหมดที่คุณต้องการ