คอนเทนเนอร์ STL หรือ Qt


185

ข้อดีและข้อเสียของการใช้ Qt container QMapคืออะไรQVectorฯลฯ ) มากกว่าเทียบเท่า STL ของพวกเขา?

ฉันเห็นเหตุผลข้อหนึ่งที่ชอบ Qt:

  • คอนเทนเนอร์ Qt สามารถส่งผ่านไปยังส่วนอื่น ๆ ของ Qt ตัวอย่างเช่นพวกเขาสามารถใช้ในการเติมQVariantและจากนั้นQSettings(มีข้อ จำกัด บางอย่างเท่านั้นQListและQMap/ QHashซึ่งมีกุญแจเป็นสายได้รับการยอมรับ)

มีอะไรอีกบ้าง?

แก้ไข : สมมติว่าแอปพลิเคชันนั้นขึ้นอยู่กับ Qt

คำตอบ:


135

ฉันเริ่มต้นด้วยการใช้std::(w)stringและคอนเทนเนอร์ STL เฉพาะและแปลงเป็น / จากรายการเทียบเท่า Qt แต่ฉันได้เปลี่ยนไปแล้วQStringและฉันพบว่าฉันกำลังใช้คอนเทนเนอร์ของ Qt มากขึ้นเรื่อย ๆ

เมื่อพูดถึงสตริงQStringมีฟังก์ชั่นการทำงานที่สมบูรณ์มากขึ้นเมื่อเทียบกับstd::basic_stringและเป็น Unicode ที่รับรู้อย่างสมบูรณ์ นอกจากนี้ยังมีการนำ COW ไปใช้อย่างมีประสิทธิภาพซึ่งฉันต้องพึ่งพาอย่างมาก

ตู้คอนเทนเนอร์ของ Qt:

  • มีการใช้งาน COW แบบเดียวกับในQStringซึ่งมีประโยชน์อย่างมากเมื่อใช้foreachมาโครของ Qt (ซึ่งทำสำเนา) และเมื่อใช้เมตาประเภทหรือสัญญาณและช่อง
  • สามารถใช้ตัววนซ้ำสไตล์ STL หรือตัววนซ้ำแบบ Java
  • สามารถสตรีมได้ด้วย QDataStream
  • มีการใช้อย่างกว้างขวางใน API ของ Qt
  • มีการใช้งานที่มั่นคงในระบบปฏิบัติการ การใช้งาน STL ต้องเป็นไปตามมาตรฐาน C ++ แต่อย่างอื่นสามารถทำได้ตามที่ต้องการ (ดูstd::stringข้อพิพาท COW) การใช้งาน STL บางอย่างไม่ดีเป็นพิเศษ
  • ให้แฮชซึ่งไม่สามารถใช้งานได้เว้นแต่ว่าคุณใช้ TR1

QTL มีปรัชญาที่แตกต่างจาก STL ซึ่งสรุปได้อย่างดีจาก J. Blanchette: "ในขณะที่ STL ของคอนเทนเนอร์นั้นได้รับการปรับให้เหมาะสมกับความเร็วดิบคลาสของคอนเทนเนอร์ของ Qt ได้รับการออกแบบอย่างระมัดระวังเพื่อให้ความสะดวกการใช้หน่วยความจำน้อยที่สุด
ลิงค์ด้านบนให้รายละเอียดเพิ่มเติมเกี่ยวกับการใช้ QTL และการเพิ่มประสิทธิภาพใดบ้าง


12
ในมาตรฐานใหม่ c ++ 0x COW ค่อนข้างออกนอกตาราง

16
เรื่อง: "ออกแบบมาอย่างพิถีพิถันเพื่อให้การใช้หน่วยความจำน้อยที่สุด [... ]" คุณไม่ควรเชื่อเรื่องการตลาด โปรไฟล์QList<double>บนสถาปัตยกรรม 32- บิตสำหรับหน่วยความจำใช้เพื่อดูด้วยตัวคุณเอง
— Marc Mutz - mmutz

11
"นอกจากนี้ยังมีการนำ COW ไปใช้อย่างมีประสิทธิภาพ": COW ไม่ใช่ทุกอย่างที่มีประสิทธิภาพเมื่อพูดถึงแอพพลิเคชั่นแบบมัลติเธรด ...
— Grizzly

5
@ MarcMutz-mmutz ลองไปที่โปรไฟล์แทนQVector QListมีคำอธิบาย Qt ที่น่ารักว่า QList นั้นถูกออกแบบมาเพื่อเก็บพอยน์เตอร์ไว้บนวัตถุ QListดังนั้นแต่ละรายการคู่สร้างแบบไดนามิกและชี้ไปยังรายการนี้จะถูกเก็บไว้เพื่อ QList ได้รับการออกแบบเป็นคอนเทนเนอร์ "กลาง" ระหว่างเวกเตอร์และรายการที่เชื่อมโยง มันไม่ได้ออกแบบมาสำหรับกรณีที่หน่วยความจำ / ประสิทธิภาพที่สำคัญ
— Dmitry Sazonov

2
@ user1095108 ไม่มีอะไรผิดปกติ ไปใช้ stl พวกเราบางคนชอบเขียนรหัสที่ถูกต้องอย่างรวดเร็ว ไม่มีอะไรผิดปกติกับสิ่งนั้น
— weberc2

178

นี่เป็นคำถามที่ตอบยาก มันสามารถต้มลงไปในการโต้แย้งทางปรัชญา / อัตนัย

ที่ถูกกล่าวว่า ...

ฉันแนะนำกฎ"เมื่ออยู่ในโรม ... ทำตามที่ชาวโรมันทำ"

ซึ่งหมายความว่าถ้าคุณอยู่ใน Qt land ให้ทำตามที่ Qt'ians ทำ นี่ไม่ได้มีไว้สำหรับความกังวลในการอ่าน / ความสอดคล้องเท่านั้น พิจารณาสิ่งที่เกิดขึ้นหากคุณเก็บทุกอย่างไว้ในคอนเทนเนอร์ stl คุณต้องส่งข้อมูลทั้งหมดนั้นไปยังฟังก์ชัน Qt คุณต้องการจัดการรหัสจำนวนมากที่คัดลอกสิ่งต่าง ๆ ลงใน / ออกจากคอนเทนเนอร์ Qt หรือไม่ รหัสของคุณขึ้นอยู่กับ Qt อย่างหนักดังนั้นจึงไม่เหมือนกับที่คุณสร้างให้เป็น "มาตรฐาน" อีกต่อไปโดยใช้คอนเทนเนอร์ stl และจุดใดของคอนเทนเนอร์ถ้าทุกครั้งที่คุณต้องการใช้เพื่อประโยชน์อะไรคุณต้องคัดลอกมันลงในคอนเทนเนอร์ Qt ที่เกี่ยวข้อง?


1
+1 คุณโดยสิ้นเชิงนั่นคือสิ่งที่ฉันพยายามอธิบายในคำถามของฉัน ("ฉันเห็นเหตุผลข้อหนึ่งที่ชอบ Qt") ดังนั้นฉันจึงแก้ไขเล็กน้อย ขอบคุณ
— Julien-L

พูดได้ดีอย่างแน่นอน หากคุณกำลังทำ QT ใช้สิ่งที่ QT! ลองนึกภาพช่วงเวลา "WTF" สำหรับผู้ดูแลเมื่อเขาเปิดแอปพลิเคชัน QT และเห็นว่า QT และ STL ใช้สลับกันได้ ที่อาจกลายเป็นฝันร้าย (ไม่จำเป็น)
— It'sPete

5
@ It'sPete STL เป็นส่วนหนึ่งของมาตรฐาน QT ไม่ใช่ รหัสใด ๆ ที่ใช้ประโยชน์จากมาตรฐานไม่ควรเรียกช่วงเวลา "WTF"
— อลิซ

6
ชาวโรมันนำเชลยเข้าไปในโคลอสเซียมแล้วตามล่าสิงโตด้วย ถ้าคุณรู้ดีกว่าอย่าทำตามนิสัยในท้องถิ่น นั่นเป็นเรื่องจริงใน Qt อย่างที่มันควรจะเป็นสำหรับคนสมัยใหม่ในจักรวรรดิโรมัน ...
— Marc Mutz - mmutz

1
@mmutz คุณบอกว่าเหมือนมันเป็นสิ่งที่ไม่ดีผมอยากจะใส่รหัสบางอย่างที่ฉันได้พบในการที่โคลีเซียมและชมการแสดง
— SLF

65

คอนเทนเนอร์ Qt นั้นมีข้อ จำกัด มากกว่า STL ตัวอย่างเล็ก ๆ น้อย ๆ ของสิ่งที่ STL เหนือกว่า (ทั้งหมดนี้ฉันเคยตีในอดีต):

  • STL ได้มาตรฐานไม่เปลี่ยนแปลงกับทุกรุ่น Qt (Qt 2 มีQList(อิงจากตัวชี้) และQValueList(อิงตามค่า); Qt 3 มีQPtrListและQValueList; Qt 4 ตอนนี้มีQListและไม่มีอะไรที่เหมือนกับQPtrList หรือ QValueList )
    . แม้ว่าคุณจะสิ้นสุดการใช้ภาชนะบรรจุ Qt ใช้ STL เข้ากันได้กับ API เซต (เช่นpush_back()ไม่append(); front()ไม่first() ... ) เพื่อหลีกเลี่ยงการย้ายอีกครั้งมา Qt 5. ในทั้งสอง Qt2-> 3 และ Qt3-> 4 ช่วงการเปลี่ยนภาพการเปลี่ยนแปลงในคอนเทนเนอร์ Qt เป็นหนึ่งในสิ่งที่ต้องใช้การเปลี่ยนรหัสส่วนใหญ่
  • คอนเทนเนอร์แบบสองทิศทาง STL ทั้งหมดมีrbegin()/ rend()ทำให้สมมาตรย้อนกลับสมมาตรเพื่อส่งต่อการทำซ้ำ ไม่ใช่ Qt container ทั้งหมดที่มีพวกมัน (ตัวเชื่อมโยงไม่ได้) ดังนั้นการวนซ้ำแบบย้อนกลับจึงมีความซับซ้อนโดยไม่จำเป็น
  • คอนเทนเนอร์ STL มีinsert()ช่วงจากประเภทที่แตกต่างกัน แต่ใช้งานร่วมกันได้ซึ่งstd::copy()จำเป็นต้องใช้น้อยกว่ามาก
  • คอนเทนเนอร์ STL มีAllocatorอาร์กิวเมนต์เท็มเพลตทำให้การจัดการหน่วยความจำแบบกำหนดเองเป็นเรื่องเล็กน้อย (จำเป็นต้องพิมพ์) เปรียบเทียบกับQt ( QLineEditจำเป็นต้องใช้ส้อมs/QString/secqstring/) แก้ไข 20171220 : สิ่งนี้ตัด Qt ออกจากความก้าวหน้าในการออกแบบตัวจัดสรรตาม C ++ 11 และ C ++ 17, cf เช่นการพูดคุยของ John Lakos ( ตอนที่ 2 )
  • ไม่มี Qt เทียบเท่ากับ std::dequeเทียบเท่ากับการเป็น
  • std::listsplice()มี เมื่อใดก็ตามที่ฉันพบตัวเองโดยใช้ก็เพราะฉันต้องการ std::listsplice()
  • std::stack, std::queueถูกต้องรวมภาชนะพื้นฐานของพวกเขาและไม่ได้สืบทอดมันเป็นQStack, QQueueทำ
  • QSetก็เหมือนไม่เหมือนstd::unordered_setstd::set
  • QListเป็นที่แปลกเพียง

หลายอย่างที่กล่าวมาข้างต้นสามารถแก้ไขได้อย่างง่ายดายใน Qtแต่ไลบรารีของตู้คอนเทนเนอร์ใน Qt นั้นดูเหมือนว่าจะประสบกับการขาดการมุ่งเน้นการพัฒนาในขณะนี้

แก้ไข 20150106 : หลังจากใช้เวลาพยายามนำ C ++ 11- สนับสนุนไปยังคลาสคอนเทนเนอร์ Qt 5 ฉันได้ตัดสินใจว่ามันไม่คุ้มค่ากับงาน ถ้าคุณดูงานที่กำลังใส่ลงในการใช้งานไลบรารีมาตรฐาน C ++ มันค่อนข้างชัดเจนว่า Qt คลาสจะไม่ตามทัน เราได้เปิดตัว Qt 5.4 ในขณะนี้และQVector ยังคงไม่ย้ายองค์ประกอบบนจัดสรรไม่ได้มีemplace_back()หรือ rvalue-push_back()... เรายังเพิ่งปฏิเสธQOptionalแม่แบบชั้นรอให้std::optionalแทน std::unique_ptrในทำนองเดียวกันสำหรับ ฉันหวังว่าแนวโน้มจะดำเนินต่อไป


3
ฮะ. ฉันถูกภายใต้การแสดงผลQList เป็นstd::dequeเท่ากับ เห็นได้ชัดว่าฉันไม่ควรอ่านเอกสาร
— Dennis Zickefoose

QVectorมีcrbeginและเป็นเพื่อนตั้งแต่ Qt 5.6
— Bart Louwers

@Alex: ใช่แล้วฉันได้เพิ่มสิ่งที่ง่าย แต่ไม่มี Qt container ทั้งหมดที่มีอยู่ (เพราะคุณไม่ได้ใช้งานstd::reverse_iteratorเกินQHash/ ตัวQMapวนซ้ำซึ่งเมื่อ dereferenced ให้ส่งคืนmapped_typeแทนvalue_type) ไม่มีอะไรที่ไม่สามารถแก้ไขได้ แต่ดูการแก้ไขของฉันตั้งแต่ปี 2015
— Marc Mutz - mmutz

@ MarcMutz-mmutz ขอบคุณสำหรับการชี้แจง
— Bart Louwers

อาจเพิ่มมูลค่าให้กับรายการความจริงที่ว่าเช่นQVectorใช้intเป็นดัชนีดังนั้น จำกัด ขนาด 31 บิต (แม้ในระบบ 64 บิต) ยิ่งกว่านั้นมันไม่สามารถแม้แต่จะเก็บINT_MAXองค์ประกอบที่มีขนาดใหญ่กว่า 1 ไบต์ได้ เช่นที่ใหญ่ที่สุดที่.size()ฉันสามารถทำได้QVector<float>บน x86_64 Linux gcc คือองค์ประกอบ 536870907 (2²⁹-5) ในขณะที่std::vector<float>จัดสรรเรียบร้อยแล้ว 4294967295 องค์ประกอบ (2³²-1; ไม่ได้ลองมากขึ้นเนื่องจากการขาด RAM สำหรับขนาดนี้ (ขนาดนี้ใช้เวลา 16 GiB แล้ว) )
— Ruslan

31

ลองแยกข้อเรียกร้องเหล่านี้ออกเป็นปรากฏการณ์ที่วัดได้จริง:

  • ไฟแช็ก: คอนเทนเนอร์ Qt ใช้หน่วยความจำน้อยกว่าคอนเทนเนอร์ STL
  • ปลอดภัยยิ่งขึ้น: ตู้คอนเทนเนอร์ Qt มีโอกาสน้อยที่จะใช้อย่างไม่เหมาะสม
  • ง่ายกว่า: คอนเทนเนอร์ Qt มีภาระทางปัญญาน้อยลง

ง่ายดาย

การอ้างสิทธิ์ที่เกิดขึ้นในบริบทนี้คือการทำซ้ำสไตล์ Java เป็นอย่างใด "ง่าย" กว่าสไตล์ STL และดังนั้น Qt ใช้งานได้ง่ายขึ้นเนื่องจากส่วนต่อประสานเพิ่มเติมนี้

สไตล์ชวา:

QListIterator<QString> i(list);
while (i.hasNext())
    qDebug() << i.next();

สไตล์ STL:

QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

สไตล์ Java iterator มีประโยชน์ในการมีขนาดเล็กลงและสะอาดขึ้นเล็กน้อย ปัญหาคือนี่ไม่ใช่สไตล์ STL จริง ๆ อีกต่อไป

สไตล์ C ++ 11 STL

for( auto i = list.begin(); i != list.end(); ++i)
    qDebug << *i;

หรือ

C ++ 11 foreach style

for (QString i : list)
    qDebug << i;

ซึ่งง่ายอย่างมากที่ไม่มีเหตุผลอะไรเลยที่จะใช้สิ่งอื่น (เว้นแต่คุณจะไม่รองรับ C ++ 11)

อย่างไรก็ตามสิ่งที่ฉันชอบคือ:

BOOST_FOREACH(QString i, list)
{
    qDebug << i;
}

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

นอกจากนี้อินเตอร์เฟส Qt foreach และ java เพิ่มโอเวอร์เฮด; พวกเขาคัดลอกโครงสร้างและให้ระดับความไม่จำเป็นของการอ้อม นี่อาจดูเหมือนไม่มาก แต่ทำไมเพิ่มเลเยอร์ของค่าใช้จ่ายเพื่อให้อินเทอร์เฟซที่ไม่มากง่ายกว่า? Java มีส่วนต่อประสานนี้เนื่องจาก java ไม่มีตัวดำเนินการมากเกินไป C ++ ทำ

ปลอดภัยมากขึ้น

เหตุผลที่ Qt ให้นั้นคือปัญหาการแบ่งปันโดยปริยายซึ่งไม่ใช่ทั้งปัญหาและโดยปริยาย อย่างไรก็ตามเกี่ยวข้องกับการแบ่งปัน

QVector<int> a, b;
a.resize(100000); // make a big vector filled with 0.

QVector<int>::iterator i = a.begin();
// WRONG way of using the iterator i:
b = a;
/*
Now we should be careful with iterator i since it will point to shared data
If we do *i = 4 then we would change the shared instance (both vectors)
The behavior differs from STL containers. Avoid doing such things in Qt.
*/

ครั้งแรกนี้ไม่ได้โดยปริยาย คุณกำลังกำหนดเวกเตอร์หนึ่งรายการให้กับอีกเวกเตอร์หนึ่งอย่างชัดเจน ข้อมูลจำเพาะตัววนซ้ำ STL ระบุอย่างชัดเจนว่าตัววนซ้ำอยู่ในคอนเทนเนอร์ดังนั้นเราจึงแนะนำคอนเทนเนอร์ที่ใช้ร่วมกันอย่างชัดเจนระหว่าง b และ a ประการที่สองนี่ไม่ใช่ปัญหา ตราบใดที่มีการปฏิบัติตามกฎทั้งหมดของข้อกำหนดตัววนซ้ำไม่มีอะไรผิดปกติ มีเพียงบางสิ่งที่ผิดพลาดอยู่ที่นี่:

b.clear(); // Now the iterator i is completely invalid.

Qt ระบุสิ่งนี้ราวกับว่ามันหมายถึงบางสิ่งบางอย่างเช่นปัญหาที่เกิดขึ้น de novo จากสถานการณ์นี้ มันไม่ได้ ตัววนซ้ำไม่ถูกต้องและเหมือนกับทุกสิ่งที่สามารถเข้าถึงได้จากหลายพื้นที่ที่แยกจากกันนี่เป็นวิธีการทำงาน ในความเป็นจริงนี้จะเกิดขึ้นพร้อมกับ Java iterators สไตล์น่ารักขอบคุณที่มันเป็นอย่างมากการพึ่งพาการใช้ร่วมกันโดยปริยายซึ่งเป็น antipattern เป็นเอกสารที่นี่และที่อื่น ๆ อีกหลายพื้นที่พื้นที่ดูเหมือนจะแปลกเป็นพิเศษสำหรับ "การเพิ่มประสิทธิภาพ" นี้ที่จะนำไปใช้ในกรอบการทำงานที่เพิ่มมากขึ้นไปสู่การทำมัลติเธรด แต่นั่นเป็นการตลาดสำหรับคุณ

ไฟแช็ก

อันนี้ค่อนข้างหลอกลวง การใช้กลยุทธ์การคัดลอก - เขียน - และการแบ่งปันและการเติบโตโดยปริยายทำให้ยากมากที่จะรับประกันว่าหน่วยความจำของคุณจะใช้คอนเทนเนอร์เท่าไรในเวลาใดก็ตาม ซึ่งแตกต่างจาก STL ซึ่งให้การรับประกันอัลกอริทึมที่แข็งแกร่งแก่คุณ

เรารู้ขอบเขตที่น้อยที่สุดของการสูญเสียพื้นที่สำหรับเวกเตอร์คือสแควร์รูทของความยาวของเวกเตอร์แต่ดูเหมือนว่าจะไม่มีวิธีการใช้สิ่งนี้ใน Qt; "การปรับให้เหมาะสม" แบบต่าง ๆ ที่พวกเขาสนับสนุนจะกีดกันคุณลักษณะการประหยัดพื้นที่ที่สำคัญมากนี้ STL ไม่ต้องการคุณลักษณะนี้ (และส่วนใหญ่ใช้การเติบโตเพิ่มขึ้นสองเท่าซึ่งสิ้นเปลืองมากกว่า) แต่สิ่งสำคัญคือต้องทราบว่าอย่างน้อยคุณสามารถใช้คุณลักษณะนี้ได้หากจำเป็น

เช่นเดียวกับรายการที่เชื่อมโยงเป็นทวีคูณซึ่งสามารถใช้การเชื่อมโยง XOr เพื่อลดพื้นที่ใช้งานได้อย่างมาก อีกครั้งนี้เป็นไปไม่ได้กับ Qt เนื่องจากเป็นข้อกำหนดสำหรับการเติบโตและ COW

COW สามารถทำให้บางสิ่งบางอย่างเบาลงได้ แต่เช่น Intrusive Containers เช่นการสนับสนุนโดยการเพิ่มและ Qt ใช้สิ่งเหล่านี้บ่อยครั้งในรุ่นก่อนหน้า แต่พวกมันไม่ได้ใช้มากนักเพราะมันยากที่จะใช้ไม่ปลอดภัยและกำหนดภาระ บนโปรแกรมเมอร์ วัวเป็นทางออกที่รบกวนน้อยกว่า แต่ไม่น่าสนใจด้วยเหตุผลที่กล่าวมาข้างต้น

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

สรุปแล้ว

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


4
คะแนนของคุณส่วนใหญ่ใช้ได้ แต่มีข้อมูลที่ทำให้เข้าใจผิดบางส่วน: Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".ตัววนซ้ำของ Java ของ Qt ไม่ได้ถูกเพิ่มลงใน C ++ 11; พวกเขาลงวันที่ก่อนวันจริง อย่างไรก็ตาม Qt foreach(QString elem, list)นั้นง่ายพอ ๆ กับ C ++ 11's foreach หรือ BOOST_FOREACH และทำงานร่วมกับคอมไพเลอร์ที่รองรับ pre-C ++ 11
— weberc2

@ weberc2 คุณกำลังสับสน; ตัวทำซ้ำสไตล์ Java ของ Qt ถูกเพิ่มไว้ด้านบนของตัววนซ้ำ C ++ (ไม่ใช่ C ++ 11) มันเป็นเลเยอร์เพิ่มเติมของสิ่งที่เป็นนามธรรม (และสิ่งที่ไม่จำเป็น) ที่ขยายอินเทอร์เฟซซึ่งไม่ใช่เรื่องง่าย และ foreach สำหรับ Qt นั้นไม่ใช่เรื่องง่ายเหมือนกับ BOOST_FOREACH เนื่องจากมันไม่ปลอดภัยและไม่ได้รับการสนับสนุนที่กว้างเท่ากัน (BOOST_FOREACH สามารถใช้กับช่วงใดก็ได้สำหรับ C ++ รุ่นใด ๆ ที่ foreach ใน QT ต้องการ C + +03 สอดคล้อง) foreach ของ QT ควรหลีกเลี่ยงค่าใช้จ่ายทั้งหมด
— Alice

So, as we can see, this interface gains us nothing except an additional interface, *on top of* an already sleek, streamlined, and modern interface. Adding an unnecessary level of abstraction on top of an already stable and usable interface? Not my idea of "easier".(เน้นที่เหมือง) คุณพูดอย่างนี้หลังจากที่คุณแสดงให้เราเห็นว่า C ++ 11 และรุ่น BOOST ของ foreach ทำให้ดูเหมือนว่าเวอร์ชั่น Qt นั้นถูกสร้างขึ้นจากหนึ่งในสองที่ไม่ได้เป็น AFAICT ฉันแน่ใจว่านั่นไม่ใช่สิ่งที่คุณหมาย แต่เป็นวิธีที่ออกมา ดังนั้น "ข้อมูลที่ทำให้เข้าใจผิด"
— weberc2

It's an additional layer of abstraction (and an unnecessary one) that bloats the interface, which is not easier.ยังไม่ชัดเจนว่าคุณเปรียบเทียบอะไร ตัววนซ้ำ C ++ 03 ตัววนซ้ำ C ++ 11 หรือไม่ BOOST_FOREACH? ถูกทุกข้อ?
— weberc2

1
ฉันแค่บอกว่าคุณมักจะคลุมเครือมากกับวิธีการทำซ้ำที่คุณอ้างถึง ฉันเชื่อว่าคุณคิดว่าคุณชัดเจนและภาษาของคุณมีเหตุผล แต่ดูเหมือนแปลกที่จะปฏิเสธที่จะระบุ เห็นด้วยที่จะไม่เห็นด้วยฉันคิดว่า
— weberc2

23

ภาชนะ STL:

  • มีการรับประกันประสิทธิภาพ
  • สามารถใช้ในอัลกอริทึม STL ซึ่งมีการรับประกันประสิทธิภาพ
  • สามารถใช้ประโยชน์จากไลบรารี C ++ ของบุคคลที่สามเช่น Boost
  • เป็นมาตรฐานและมีแนวโน้มที่จะมีอายุยืนกว่าโซลูชันที่เป็นกรรมสิทธิ์
  • ส่งเสริมการเขียนโปรแกรมทั่วไปของอัลกอริทึมและโครงสร้างข้อมูล หากคุณเขียนอัลกอริธึมและโครงสร้างข้อมูลใหม่ที่สอดคล้องกับ STL คุณสามารถใช้ประโยชน์จากสิ่งที่ STL ได้จัดเตรียมไว้ให้โดยไม่มีค่าใช้จ่าย

5
ทั้งหมดข้างต้นยกเว้นการเป็นมาตรฐานนั้นเป็นจริงสำหรับ QTL ด้วยเช่นกันหากคุณรวบรวม Qt ด้วยการสนับสนุน STL (ค่าเริ่มต้น) การสนับสนุน STL ประกอบด้วยฟังก์ชันตัววนซ้ำตัวพิมพ์คอนเทนเนอร์ (const_iterator ฯลฯ ) ฟังก์ชันการแปลง (ถึง / จาก STL)
— rpg

2
Qt ไม่ได้เป็นกรรมสิทธิ์
— txwikinger

3
@rpg เกือบทั้งหมดของพวกเขาไม่เป็นความจริงของ QTL; QTL ไม่มีการรับประกันประสิทธิภาพที่แข็งแกร่ง (ในขณะที่พวกเขาได้ทำลายพวกเขาในอดีต) ไม่เป็นไปตาม STL (ไม่ย้อนกลับและดังนั้นจึงไม่สามารถใช้โดยการเพิ่มมาก) ไม่ได้มาตรฐาน (พวกเขาเปลี่ยนแปลงตลอดเวลาระหว่างรุ่น) และทำ ไม่สนับสนุนการเขียนโปรแกรมทั่วไป (พวกเขาไม่มีข้อโต้แย้งแม่แบบสำหรับผู้จัดสรรเช่น)
— อลิซ

15

คอนเทนเนอร์ Qt ใช้สำนวนการคัดลอกเมื่อเขียน


2
+1 อาจเป็นข้อได้เปรียบที่สำคัญในประสิทธิภาพและทรัพยากร
— RedGlyph

32
หรืออาจเป็นข้อเสียที่สำคัญ ดูgotw.ca/publications/optimizations.htm
— Kaz Dragon

3
refcount อะตอมดูเหมือนว่าจะค่อนข้างดี: labs.trolltech.com/blogs/2006/10/16/…
— rpg

คอนเทนเนอร์ STL มีอิสระที่จะใช้สำนวนใด ๆ ที่มีอยู่ตราบเท่าที่พวกเขาตอบสนองการรับประกันประสิทธิภาพและสเปค COW ใช้ได้แม้ภายใต้ C ++ 11 / C ++ 14 STL
— อลิซ

1
@Alice COW ไม่ใช่การใช้งานที่ถูกต้องเป็นส่วนใหญ่เพราะจะทำลายความซับซ้อนของมาตรฐานและการรับรองความถูกต้องของตัววนซ้ำในเกือบทุกกรณี หนึ่งในไม่กี่คลาสที่สามารถนำไปใช้กับ COW ได้std::basic_stringและมาตรฐานได้ดำเนินการกับ C ++ 11 เพื่อทำให้สิ่งนี้ไม่สอดคล้อง
— Tiago Gomes

9

หนึ่งในประเด็นหลักคือ API ของ Qt คาดหวังให้คุณให้ข้อมูลในคอนเทนเนอร์ของ Qt ดังนั้นคุณอาจใช้ Qt container แทนการเปลี่ยนไปมาระหว่างสองอย่าง

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


1
อัตราที่คุณต้อง "แปลงกลับไปกลับมา" ระหว่างคอนเทนเนอร์ STL และ Qt ในแอปพลิเคชันจริงที่ใช้ STL ยกเว้นการเชื่อมต่อกับ Qt โดยทั่วไปจะประเมินค่าสูงเกินไปอย่างมาก เวลาส่วนใหญ่ที่คุณทำ std :: transform มาถึง / จากเลเยอร์การนำเสนอ (ซึ่งใช้ Qt) และคุณจะได้รับ container switch ฟรี ผู้ที่สนใจสามารถเข้าไปดูโครงการต่างๆได้kde.org/projects/kde/kdepim/repository/revisions/…เพื่อดูตัวเอง
— Marc Mutz - mmutz

8

หากข้อมูลที่คุณทำงานด้วยส่วนใหญ่จะใช้เพื่อขับเคลื่อน UI แบบอิง Qt ให้ใช้คอนเทนเนอร์ Qt อย่างแน่นอน

หากข้อมูลส่วนใหญ่จะใช้ภายในแอพและคุณไม่น่าจะย้ายออกจาก Qt จากนั้นแยกแยะปัญหาด้านประสิทธิภาพใช้ Qt container เพราะจะทำให้บิตของข้อมูลที่ไปยัง UI ง่ายขึ้นในการจัดการ

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


7

นอกเหนือจากความแตกต่างของ COW คอนเทนเนอร์ STL ได้รับการสนับสนุนอย่างกว้างขวางในหลากหลายแพลตฟอร์ม Qt นั้นสามารถพกพาได้หากคุณ จำกัด งานของคุณไว้ที่แพลตฟอร์ม "หลัก" แต่ STL นั้นมีอยู่ในแพลตฟอร์มที่คลุมเครืออื่น ๆ อีกมากมายเช่น (DSP ของ Texas Instruments)

เนื่องจาก STL เป็นมาตรฐานแทนที่จะควบคุมโดย บริษัท เดียวโดยทั่วไปมีโปรแกรมเมอร์ที่สามารถอ่านเข้าใจและแก้ไขรหัส STL และแหล่งข้อมูลเพิ่มเติม (หนังสือฟอรัมออนไลน์การประชุมและอื่น ๆ ) เพื่อสนับสนุนพวกเขาใน ทำสิ่งนี้มากกว่ามีเพื่อ Qt ไม่ได้หมายความว่าเราควรหลีกเลี่ยง Qt ด้วยเหตุผลนี้เพียงลำพัง เพียงแค่นั้นทุกสิ่งอื่น ๆ ที่เท่าเทียมกันคุณควรเริ่มต้นที่ STL แต่แน่นอนว่าทุกสิ่งไม่เท่ากันดังนั้นคุณจะต้องตัดสินใจในบริบทของคุณเองซึ่งเหมาะสมที่สุด

ในเรื่องของคำตอบของ AlexKR: รับประกันประสิทธิภาพ STL ภายในขีด จำกัด แต่การใช้งานที่กำหนดอาจใช้ประโยชน์จากรายละเอียดที่ขึ้นกับแพลตฟอร์มเพื่อเพิ่มความเร็ว STL ดังนั้นในแง่นั้นคุณอาจได้รับผลลัพธ์ที่แตกต่างกันในแพลตฟอร์มที่แตกต่างกัน แต่จะไม่ช้ากว่าการรับประกันที่ชัดเจน (modulo bug)


9
เกี่ยวกับประเด็นแรกของคุณ: ฉันถือว่า OP หมายถึงโครงการที่ใช้ Qt อยู่แล้วดังนั้นจึง จำกัด เฉพาะแพลตฟอร์ม "หลัก" ดูเหมือนว่าไม่น่าเป็นไปได้ที่บางคนจะดึงไลบรารี่รุ่นหนาเช่น Qt สำหรับคลาสคอนเทนเนอร์
— ThisSuitIsBlackNot

4

ห้าเซนต์ของฉัน: ตู้คอนเทนเนอร์ Qt ควรทำงานคล้ายกับแพลตฟอร์มที่แตกต่างกัน ในขณะที่คอนเทนเนอร์ STL ขึ้นอยู่กับการใช้ STL คุณอาจได้รับผลการปฏิบัติงานที่แตกต่างกัน

แก้ไข: ฉันไม่ได้บอกว่า STL นั้น "ช้าลง" แต่ฉันชี้ไปที่ผลกระทบของรายละเอียดการใช้งานที่หลากหลาย
กรุณาตรวจสอบนี้และแล้วบางทีนี้
และไม่ใช่ปัญหาที่แท้จริงของ STL เห็นได้ชัดว่าถ้าคุณมีความแตกต่างอย่างมีนัยสำคัญในการปฏิบัติงานแล้วมีปัญหาในรหัสที่ใช้ STL


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

1
หากคุณยึดติดกับสิ่งที่ STL สัญญา (แทนที่จะสมมติว่าจะนำไปใช้อย่างไร) คุณจะไม่มีปัญหาในการย้ายระหว่างแพลตฟอร์มด้วย STL เช่นเดียวกับ Qt
— Michael Kohne

นี่คือสิ่งที่ตรงกันข้ามจริง คอนเทนเนอร์ STL ทำงานเหมือนกันทุกแพลตฟอร์ม ถ้าพวกเขาทำไม่ได้พวกเขาไม่ใช่ STL อย่างไรก็ตาม QT เปลี่ยนประสิทธิภาพอย่างมากจากรุ่นเป็นรุ่นดังนั้นบนแพลตฟอร์มที่มี QT4.0 แทนที่จะเป็น QT4.8 คุณสามารถได้รับการเปลี่ยนแปลงที่ร้ายแรง
— Alice

1
คุณกำลังสับสนกับประสิทธิภาพที่แตกต่างกันสองประเภท ประสิทธิภาพอัลกอริทึมและประสิทธิภาพการคำนวณเชิงปฏิบัติ การใช้งาน STL ทั้งหมดรับประกันประสิทธิภาพของอัลกอริทึมเดียวกัน หากเวกเตอร์ของคุณใช้เวลาในการบันทึก (n) เพื่อจัดทำดัชนีองค์ประกอบมันไม่ใช่เวกเตอร์ STL ลิงก์ของคุณชี้ไปที่ประสิทธิภาพการคำนวณเชิงปฏิบัติซึ่งไม่มีความหมายในการสนทนานี้ QT เปลี่ยนอัลกอริธึมระหว่างเวอร์ชันและ C ++ เดียวกันบนแพลตฟอร์มที่ต่างกันทำให้ประสิทธิภาพแตกต่างกัน ในประสบการณ์ของฉันเหล่านี้อ่อนกว่าความแตกต่างในประสิทธิภาพ STL
— อลิซ

3

ฉันคิดว่ามันขึ้นอยู่กับวิธีที่คุณใช้ Qt หากคุณใช้ผลิตภัณฑ์นี้กับผลิตภัณฑ์ของคุณมากกว่าที่คิดว่าเหมาะสมที่จะใช้ Qt container หากคุณมีเฉพาะส่วน (เช่น) ส่วน UI อาจเป็นการดีกว่าถ้าใช้คอนเทนเนอร์มาตรฐาน C ++


3

ฉันเห็นว่า STL เป็นซอฟต์แวร์ที่ยอดเยี่ยมอย่างไรก็ตามหากฉันต้องทำโปรแกรม KDE หรือ Qt ที่เกี่ยวข้องกับ QT นั้นเป็นวิธีที่จะไป นอกจากนี้ยังขึ้นอยู่กับคอมไพเลอร์ที่คุณใช้ด้วย GCC STL ใช้งานได้ดี แต่ถ้าคุณต้องใช้คำว่า SUN Studio CC ดังนั้น STL จะทำให้คุณปวดหัวมากที่สุดเพราะคอมไพเลอร์ไม่ใช่ STL ต่อ se ในกรณีเช่นนี้เนื่องจากคอมไพเลอร์จะทำให้คุณปวดหัวเพียงใช้ Qt เพื่อช่วยคุณประหยัดปัญหา แค่ 2 เซ็นต์ของฉัน ...


3

มีข้อ จำกัด ขนาดใหญ่ (บางครั้ง) ใน QVector สามารถจัดสรรหน่วยความจำภายในไบต์ได้เท่านั้น (โปรดทราบว่าขีด จำกัด มีหน่วยเป็นไบต์ไม่ได้อยู่ในจำนวนองค์ประกอบ) นี่หมายความว่าการพยายามจัดสรรบล็อกหน่วยความจำต่อเนื่องที่มีขนาดใหญ่กว่า ~ 2GB ด้วย QVector จะทำให้เกิดความผิดพลาด สิ่งนี้เกิดขึ้นกับ Qt 4 และ 5 std :: vector ไม่มีข้อ จำกัด ดังกล่าว


0

เหตุผลหลักที่จะไปกับคอนเทนเนอร์ STL สำหรับฉันคือถ้าคุณต้องการตัวจัดสรรแบบกำหนดเองเพื่อนำหน่วยความจำกลับมาใช้ในคอนเทนเนอร์ขนาดใหญ่มาก สมมติว่าคุณมี QMap ที่เก็บข้อมูล 1000000 รายการ (คู่ของคีย์ / ค่า) ใน Qt ที่แสดงถึงการจัดสรรที่แน่นอน 1000000 ล้าน (newโทร)ไม่ว่าจะเกิดอะไรขึ้น ใน STL คุณสามารถสร้างตัวจัดสรรแบบกำหนดเองที่จัดสรรภายในหน่วยความจำทั้งหมดในครั้งเดียวและกำหนดให้กับแต่ละรายการเมื่อแผนที่ถูกเติม

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


ไม่ได้พยายามที่จะปกป้อง QTL ที่นี่ แต่คุณสามารถมีความเชี่ยวชาญQMapNode<K,V>ของคุณK, เพื่อให้คุณเองV operator new
— Marc Mutz - mmutz
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.