Mari pilah klaim-klaim ini menjadi fenomena terukur yang sebenarnya:
- Lebih ringan: Wadah Qt menggunakan lebih sedikit memori daripada wadah STL
- Lebih aman: Wadah Qt memiliki peluang lebih sedikit untuk digunakan dengan tidak patut
- Lebih mudah: Wadah Qt mengurangi beban intelektual
Lebih mudah
Klaim yang dibuat dalam konteks ini adalah bahwa iterasi gaya java entah bagaimana "lebih mudah" daripada gaya STL, dan karenanya Qt lebih mudah digunakan karena antarmuka tambahan ini.
Gaya Jawa:
QListIterator<QString> i(list);
while (i.hasNext())
qDebug() << i.next();
Gaya STL:
QList<QString>::iterator i;
for (i = list.begin(); i != list.end(); ++i)
qDebug << *i;
Gaya iterator Java memiliki keuntungan menjadi sedikit lebih kecil dan lebih bersih. Masalahnya adalah, ini bukan gaya STL lagi.
C ++ 11 STL Style
for( auto i = list.begin(); i != list.end(); ++i)
qDebug << *i;
atau
C ++ 11 gaya foreach
for (QString i : list)
qDebug << i;
Yang sangat sederhana sehingga tidak ada alasan untuk menggunakan hal lain (kecuali Anda tidak mendukung C ++ 11).
Namun, favorit saya adalah:
BOOST_FOREACH(QString i, list)
{
qDebug << i;
}
Jadi, seperti yang bisa kita lihat, antarmuka ini tidak memberi kita apa-apa selain antarmuka tambahan, selain antarmuka yang sudah ramping, ramping, dan modern. Menambahkan level abstraksi yang tidak perlu di atas antarmuka yang sudah stabil dan dapat digunakan? Bukan ide saya "lebih mudah".
Juga, antarmuka Qt foreach dan java menambahkan overhead; mereka menyalin struktur, dan memberikan tingkat tipuan yang tidak perlu. Ini mungkin tidak terlalu banyak, tetapi mengapa menambahkan lapisan overhead untuk menyediakan antarmuka yang tidak terlalu sederhana? Java memiliki antarmuka ini karena java tidak memiliki operator kelebihan; C ++ tidak.
Lebih aman
Pembenaran yang diberikan Qt adalah masalah berbagi implisit, yang tidak implisit maupun masalah. Namun itu melibatkan berbagi.
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.
*/
Pertama, ini bukan implisit; Anda secara eksplisit menetapkan satu vektor ke yang lain. Spesifikasi iterator STL dengan jelas menunjukkan bahwa iterator termasuk dalam wadah, jadi kami telah dengan jelas memperkenalkan wadah bersama antara b dan a. Kedua, ini bukan masalah; selama semua aturan spesifikasi iterator dipatuhi, sama sekali tidak ada yang salah. Satu-satunya saat ada yang salah ada di sini:
b.clear(); // Now the iterator i is completely invalid.
Qt menetapkan ini seolah-olah itu berarti sesuatu, seperti masalah muncul de novo dari skenario ini. Tidak. Iterator tidak valid, dan sama seperti apa pun yang dapat diakses dari beberapa area terpisah, ini hanya cara kerjanya. Bahkan, ini akan terjadi dengan mudah dengan iterator gaya Java di Qt, berkat sangat bergantung pada berbagi implisit, yang merupakan antipemutakhir seperti yang didokumentasikan di sini , dan di banyak daerah lainnya . Tampaknya aneh untuk "optimasi" ini mulai digunakan dalam kerangka kerja yang bergerak semakin banyak menuju multithreading, tapi itu pemasaran untuk Anda.
Lebih ringan
Yang ini agak rumit. Penggunaan Copy-On-Write dan Berbagi Secara implisit dan Strategi Pertumbuhan membuatnya sangat sulit untuk benar-benar membuat jaminan tentang berapa banyak memori yang akan digunakan wadah Anda pada waktu tertentu. Ini tidak seperti STL, yang memberi Anda jaminan algoritmik yang kuat.
Kita tahu batas minimal ruang terbuang untuk vektor adalah akar kuadrat dari panjang vektor , tetapi tampaknya tidak ada cara untuk mengimplementasikannya dalam Qt; berbagai "optimisasi" yang didukungnya akan menghalangi fitur penghematan ruang yang sangat penting ini. STL tidak memerlukan fitur ini (dan sebagian besar menggunakan pertumbuhan dua kali lipat, yang lebih boros), tetapi penting untuk dicatat bahwa Anda setidaknya bisa mengimplementasikan fitur ini, jika perlu.
Hal yang sama berlaku untuk daftar tertaut ganda, yang dapat menggunakan tautan XOr untuk secara drastis mengurangi ruang yang digunakan. Sekali lagi, ini tidak mungkin dengan Qt, karena persyaratan untuk pertumbuhan dan SAP.
SAP memang dapat membuat sesuatu lebih ringan, tetapi Wadah Intrusif, seperti didukung oleh boost , dan Qt sering digunakan dalam versi sebelumnya, tetapi mereka tidak digunakan lagi karena mereka sulit digunakan, tidak aman, dan membebani beban. pada programmer. SAP adalah solusi yang jauh lebih tidak mengganggu, tetapi tidak menarik karena alasan yang disebutkan di atas.
Tidak ada alasan mengapa Anda tidak bisa menggunakan wadah STL dengan biaya memori yang sama atau kurang dari wadah Qt, dengan manfaat tambahan sebenarnya mengetahui berapa banyak memori yang akan Anda buang pada waktu tertentu. Sayangnya, mustahil untuk membandingkan keduanya dalam penggunaan memori mentah, karena tolok ukur seperti itu akan menunjukkan hasil yang sangat berbeda dalam kasus penggunaan yang berbeda, yang merupakan jenis masalah yang STL dirancang untuk diperbaiki.
Kesimpulannya
Hindari penggunaan Qt Containers bila memungkinkan untuk melakukannya tanpa membebankan biaya penyalinan, dan gunakan iterasi tipe STL (mungkin melalui pembungkus atau sintaks baru), bila memungkinkan.