คอนเทนเนอร์ 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.