ฉันได้ยินมาว่าauto_ptr
กำลังเลิกใช้งานใน C ++ 11 เหตุผลนี้คืออะไร?
นอกจากนี้ผมอยากจะทราบความแตกต่างระหว่างและauto_ptr
shared_ptr
ฉันได้ยินมาว่าauto_ptr
กำลังเลิกใช้งานใน C ++ 11 เหตุผลนี้คืออะไร?
นอกจากนี้ผมอยากจะทราบความแตกต่างระหว่างและauto_ptr
shared_ptr
คำตอบ:
ทดแทนโดยตรงauto_ptr
(หรือสิ่งที่ใกล้เคียงกับหนึ่งอยู่แล้ว) unique_ptr
คือ เท่าที่ "ปัญหา" ดำเนินไปมันค่อนข้างง่าย: auto_ptr
โอนความเป็นเจ้าของเมื่อได้รับมอบหมาย unique_ptr
ยังโอนความเป็นเจ้าของ แต่ด้วยการเข้ารหัสความหมายของการเคลื่อนไหวและความมหัศจรรย์ของการอ้างอิง rvalue มันสามารถทำได้อย่างเป็นธรรมชาติมากขึ้น นอกจากนี้ยัง "พอดี" กับส่วนที่เหลือของไลบรารีมาตรฐานที่ดีกว่ามาก (แต่ในความเป็นธรรมบางส่วนต้องขอบคุณห้องสมุดที่เหลือที่เปลี่ยนไปเพื่อรองรับความหมายการย้ายแทนที่จะต้องคัดลอกเสมอไป)
การเปลี่ยนชื่อยังเป็น (IMO) ซึ่งเป็นสิ่งที่น่ายินดี - auto_ptr
ไม่ได้บอกอะไรคุณมากนักเกี่ยวกับสิ่งที่พยายามทำให้เป็นอัตโนมัติในขณะที่unique_ptr
คำอธิบายที่สมเหตุสมผล (ถ้าสั้น) ของสิ่งที่ให้มา
auto_ptr
ชื่อ: auto แนะนำอัตโนมัติเช่นเดียวกับในตัวแปรอัตโนมัติและอ้างถึงสิ่งหนึ่งที่auto_ptr
ทำ: ทำลายทรัพยากรที่มีการจัดการในตัวทำลาย (เมื่ออยู่นอกขอบเขต)
auto_ptr
: open-std.org/jtc1/sc22/wg21/docs/papers/2005/…
std::sort
ไม่มีความเชี่ยวชาญสำหรับunique_ptr
. แต่มีการระบุอีกครั้งว่าห้ามคัดลอก ดังนั้นauto_ptr
จริงไม่sort
ทำงานร่วมกับโมเดิร์น แต่ C ++ 98/03 sort
เป็นเพียงขั้นตอนวิธีการเช่นที่นี่: ใด ๆขั้นตอนวิธีการทั่วไป (STD จัดหรือผู้ใช้ที่เขียน) ที่สันนิษฐานว่าไวยากรณ์สำเนามีความหมายสำเนาอาจจะมีข้อผิดพลาดเวลาทำงานถ้าใช้กับauto_ptr
เพราะauto_ptr
เงียบย้ายด้วยไวยากรณ์การคัดลอก ปัญหาคือมากsort
มีขนาดใหญ่กว่าเพียง
ฉันพบว่าคำตอบที่มีอยู่นั้นยอดเยี่ยม แต่จาก PoV ของพอยน์เตอร์ IMO คำตอบที่ดีควรมีคำตอบจากมุมมองของผู้ใช้ / โปรแกรมเมอร์
สิ่งแรกก่อน (ตามที่ Jerry Coffin ชี้ในคำตอบของเขา)
shared_ptr: หากคุณกังวลเกี่ยวกับการปลดปล่อยทรัพยากร / หน่วยความจำและหากคุณมีมากกว่าหนึ่งฟังก์ชันที่สามารถใช้อ็อบเจ็กต์ AT-DIFFERENT ครั้งให้ไปที่ shared_ptr
ตามเวลาที่แตกต่างกันให้นึกถึงสถานการณ์ที่ object-ptr ถูกเก็บไว้ในโครงสร้างข้อมูลหลายรายการและเข้าถึงได้ในภายหลัง แน่นอนว่าหลายเธรดเป็นอีกตัวอย่างหนึ่ง
unique_ptr:หากสิ่งที่คุณกังวลคือการเพิ่มหน่วยความจำและการเข้าถึงอ็อบเจ็กต์คือ SEQUENTIAL ให้ไปที่ unique_ptr
ตามลำดับฉันหมายถึงวัตถุใด ๆ ที่จะเข้าถึงได้จากบริบทเดียว เช่นวัตถุที่สร้างขึ้นและใช้ทันทีหลังจากสร้างโดยผู้สร้าง หลังจากสร้างวัตถุจะถูกเก็บไว้ในโครงสร้างข้อมูลFIRST จากนั้นวัตถุจะถูกทำลายหลังจากโครงสร้างข้อมูล ONE หรือถูกย้ายไปยังโครงสร้างข้อมูลที่สอง
จากบรรทัดนี้ฉันจะอ้างถึง _ptr ที่ใช้ร่วมกัน / ไม่ซ้ำกันเป็นตัวชี้อัจฉริยะ (auto_ptr ยังเป็นตัวชี้อัจฉริยะ แต่เนื่องจากมีข้อบกพร่องในการออกแบบซึ่งกำลังเลิกใช้งานและซึ่งฉันคิดว่าฉันจะชี้ให้เห็นในบรรทัดถัดไปไม่ควรจัดกลุ่มด้วยตัวชี้อัจฉริยะ)
เหตุผลที่สำคัญที่สุดเพียงประการเดียวที่ทำให้ auto_ptr เลิกใช้งานเนื่องจากสมาร์ทพอยน์เตอร์คือการ กำหนด - ความหมาย หากไม่เป็นเช่นนั้นพวกเขาจะได้เพิ่มความหมายใหม่ทั้งหมดของความหมายการย้ายไปยัง auto_ptr แทนที่จะเลิกใช้งาน เนื่องจากการกำหนดความหมายเป็นคุณลักษณะที่ไม่ชอบมากที่สุดพวกเขาจึงต้องการให้คุณลักษณะนั้นหายไป แต่เนื่องจากมีการเขียนโค้ดที่ใช้ความหมายนั้น (ซึ่งคณะกรรมการมาตรฐานไม่สามารถเปลี่ยนแปลงได้) พวกเขาจึงต้องปล่อย auto_ptr ไปแทน แก้ไขมัน
จากลิงค์: http://www.cplusplus.com/reference/memory/unique_ptr/operator=/
ประเภทของงานที่สนับสนุนโดย unqiue_ptr
จาก: http://www.cplusplus.com/reference/memory/auto_ptr/operator=/
ประเภทงานที่รองรับโดย auto_ptr
ตอนนี้มาถึงเหตุผลว่าทำไมการกำหนดสำเนาถึงไม่ชอบฉันจึงมีทฤษฎีนี้:
พฤติกรรมที่ไม่ได้ตั้งใจเป็นสิ่งที่ไม่ชอบจริงๆและด้วยเหตุนี้จึงไม่ชอบสำหรับ auto_ptr
(สำหรับโปรแกรมเมอร์ 3.1415926536% ที่จงใจต้องการโอนความเป็นเจ้าของ C ++ 11 ให้ std :: move () ซึ่งทำให้ความตั้งใจของพวกเขาชัดเจนสำหรับนักศึกษาฝึกงานทุกคนที่กำลังจะอ่านและรักษารหัส)
auto_ptr
ค่าสองค่าชี้ไปที่วัตถุเดียวกัน (เนื่องจากพวกเขาไม่ได้ให้ความเป็นเจ้าของร่วมกันคนแรกที่ตายจะทิ้งอีกอย่างไว้ด้วยมรดกที่ร้ายแรงนี่เป็นเรื่องจริงสำหรับunique_ptr
การใช้งาน) คุณช่วยแนะนำสิ่งที่ตั้งใจไว้ได้ไหมที่เหลือ 96.8584073465% ของการใช้งานทั้งหมด?
*a=*b;
นี่มีเพียงค่า b เท่านั้นที่ถูกคัดลอกไปยังไฟล์. ฉันหวังว่าการเป็นเจ้าของทั้ง a และ b ยังคงอยู่กับคนเดิม ที่คุณกล่าวถึงเช่นการเป็นหนี้จะถูกโอน จะเป็นยังไง?
auto_ptr
วัตถุนั้นเอง การกำหนดให้กับ / จากค่าที่ชี้ไปยังไม่มีผลกระทบหรือความเกี่ยวข้องกับความเป็นเจ้าของ ฉันหวังว่าคุณจะยังไม่ได้ใช้auto_ptr
?
shared_ptr
สามารถเก็บไว้ในภาชนะ auto_ptr
ลาด.
BTW unique_ptr
เป็นการauto_ptr
ทดแทนโดยตรงโดยรวมคุณสมบัติที่ดีที่สุดของทั้งสองstd::auto_ptr
และboost::scoped_ptr
.
ยังต้องใช้เวลาอีกในการอธิบายความแตกต่าง ....
ตามหน้าที่แล้ว C ++ 11 std::unique_ptr
คือ "คงที่" std::auto_ptr
: ทั้งสองอย่างเหมาะสมเมื่อ - ณ เวลาใด ๆ ในระหว่างการดำเนินการ - ควรมีเจ้าของตัวชี้อัจฉริยะเพียงตัวเดียวสำหรับวัตถุที่ชี้ไปที่
ความแตกต่างที่สำคัญคือการสร้างสำเนาหรือการมอบหมายจากตัวชี้อัจฉริยะอื่นที่ยังไม่หมดอายุซึ่งแสดงไว้ใน=>
บรรทัดด้านล่าง:
std::auto_ptr<T> ap(...);
std::auto_ptr<T> ap2(get_ap_to_T()); // take expiring ownership
=> std::auto_ptr<T> ap3(ap); // take un-expiring ownership ala ap3(ap.release());
ap->xyz; // oops... can still try to use ap, expecting it to be non-NULL
std::unique_ptr<T> up(...);
std::unique_ptr<T> up2(get_up_to_T()); // take expiring ownership
=> std::unique_ptr<T> up3(up); // COMPILE ERROR: can't take un-expiring ownership
=> std::unique_ptr<T> up4(std::move(up)); // EXPLICIT code allowed
=> std::unique_ptr<T> up4(up.release()); // EXPLICIT code allowed
ด้านบนap3
"ขโมย" ความเป็นเจ้าของอย่างเงียบ ๆ*ap
ปล่อยให้ap
ตั้งค่าเป็น a nullptr
และปัญหาก็คืออาจเกิดขึ้นได้ง่ายเกินไปโดยที่โปรแกรมเมอร์ไม่ได้คำนึงถึงความปลอดภัย
ตัวอย่างเช่นหาก a class
/ struct
มีstd::auto_ptr
สมาชิกการทำสำเนาอินสแตนซ์release
ตัวชี้จากอินสแตนซ์จะถูกคัดลอกนั่นคือความหมายที่แปลกและสับสนอย่างอันตรายเนื่องจากโดยปกติการคัดลอกบางสิ่งจะไม่แก้ไข เป็นเรื่องง่ายสำหรับผู้เขียนคลาส / โครงสร้างที่จะมองข้ามการเปิดตัวของตัวชี้เมื่อให้เหตุผลเกี่ยวกับค่าคงที่และสถานะและด้วยเหตุนี้จึงมีความพยายามที่จะหักค่าตัวชี้สมาร์ทโดยไม่ได้ตั้งใจในขณะที่เป็นโมฆะหรือเพียงแค่ไม่คาดว่าจะมีการเข้าถึง / เป็นเจ้าของข้อมูลที่ชี้ไป
auto_ptr ไม่สามารถนำมาใช้ในภาชนะ STL เพราะมันมีตัวสร้างสำเนาที่ไม่ตรงตามความต้องการของภาชนะCopyConstructible unique_ptr ไม่ได้ใช้ตัวสร้างการคัดลอกดังนั้นคอนเทนเนอร์จึงใช้วิธีอื่น unique_ptr สามารถใช้ในคอนเทนเนอร์ได้และเร็วกว่าสำหรับอัลกอริทึม std มากกว่า shared_ptr
#include <iostream>
#include <type_traits>
#include <vector>
#include <memory>
using namespace std;
int main() {
cout << boolalpha;
cout << "is_copy_constructible:" << endl;
cout << "auto_ptr: " << is_copy_constructible< auto_ptr<int> >::value << endl;
cout << "unique_ptr: " << is_copy_constructible< unique_ptr<int> >::value << endl;
cout << "shared_ptr: " << is_copy_constructible< shared_ptr<int> >::value << endl;
vector<int> i_v;
i_v.push_back(1);
cout << "i_v=" << i_v[0] << endl;
vector<int> i_v2=i_v;
cout << "i_v2=" << i_v2[0] << endl;
vector< unique_ptr<int> > u_v;
u_v.push_back(unique_ptr<int>(new int(2)));
cout << "u_v=" << *u_v[0] << endl;
//vector< unique_ptr<int> > u_v2=u_v; //will not compile, need is_copy_constructible == true
vector< unique_ptr<int> > u_v2 =std::move(u_v); // but can be moved
cout << "u_v2=" << *u_v2[0] << " length u_v: " <<u_v.size() << endl;
vector< shared_ptr<int> > s_v;
shared_ptr<int> s(new int(3));
s_v.push_back(s);
cout << "s_v=" << *s_v[0] << endl;
vector< shared_ptr<int> > s_v2=s_v;
cout << "s_v2=" << *s_v2[0] << endl;
vector< auto_ptr<int> > a_v; //USAGE ERROR
return 0;
}
>cxx test1.cpp -o test1
test1.cpp: In function âint main()â:
test1.cpp:33:11: warning: âauto_ptrâ is deprecated (declared at /apps/hermes/sw/gcc/gcc-4.8.5/include/c++/4.8.5/backward/auto_ptr.h:87) [-Wdeprecated-declarations]
vector< auto_ptr<int> > a_v; //USAGE ERROR
^
>./test1
is_copy_constructible:
auto_ptr: false
unique_ptr: false
shared_ptr: true
i_v=1
i_v2=1
u_v=2
s_v=3
s_v2=3