Menggunakan array atau std :: vektor dalam C ++, apa kesenjangan kinerja?

208

Dalam kursus C ++ kami, mereka menyarankan untuk tidak menggunakan array C ++ pada proyek baru lagi. Sejauh yang saya tahu Stroustroup sendiri menyarankan untuk tidak menggunakan array. Tetapi apakah ada perbedaan kinerja yang signifikan?

tunnuz
sumber
2
Mengapa Anda berpikir ada kesenjangan kinerja.
Martin York
99
Karena biasanya dengan fungsionalitas yang lebih baik muncul kinerja terburuk.
tunnuz
19
Saya setuju tentang pengoptimalan prematur tetapi memilih metode penyimpanan yang lebih baik di muka sangat masuk akal. Seringkali di dunia nyata kode perlu dikirim dan produk berikutnya dikembangkan dan langkah optimasi tidak pernah terjadi.
Semut
132
Saya berharap orang-orang berhenti berteriak "optimisasi prematur!" setiap kali seseorang mengajukan pertanyaan sederhana terkait kinerja! jawab pertanyaan dan jangan hanya menganggap orang melakukan sesuatu secara prematur.
d7samurai
4
@ d7samaurai: setuju, saya belum melihat ada yang mencoba menggunakanint main(int argc, const std::vector<string>& argv)
Mark K Cowan

Jawaban:

189

Menggunakan array C ++ dengan new(yaitu, menggunakan array dinamis) harus dihindari. Ada masalah Anda harus melacak ukurannya, dan Anda harus menghapusnya secara manual dan melakukan semua jenis pembersihan.

Menggunakan array pada stack juga tidak disarankan karena Anda tidak memiliki pemeriksaan jangkauan, dan melewatkan array akan kehilangan informasi tentang ukurannya (konversi array ke pointer). Anda harus menggunakan boost::arraydalam kasus itu, yang membungkus array C ++ di kelas kecil dan menyediakan sizefungsi dan iterator untuk beralih di atasnya.

Sekarang array std :: vector vs asli C ++ (diambil dari internet):

// Comparison of assembly code generated for basic indexing, dereferencing, 
// and increment operations on vectors and arrays/pointers.

// Assembly code was generated by gcc 4.1.0 invoked with  g++ -O3 -S  on a 
// x86_64-suse-linux machine.

#include <vector>

struct S
{
  int padding;

  std::vector<int> v;
  int * p;
  std::vector<int>::iterator i;
};

int pointer_index (S & s) { return s.p[3]; }
  // movq    32(%rdi), %rax
  // movl    12(%rax), %eax
  // ret

int vector_index (S & s) { return s.v[3]; }
  // movq    8(%rdi), %rax
  // movl    12(%rax), %eax
  // ret

// Conclusion: Indexing a vector is the same damn thing as indexing a pointer.

int pointer_deref (S & s) { return *s.p; }
  // movq    32(%rdi), %rax
  // movl    (%rax), %eax
  // ret

int iterator_deref (S & s) { return *s.i; }
  // movq    40(%rdi), %rax
  // movl    (%rax), %eax
  // ret

// Conclusion: Dereferencing a vector iterator is the same damn thing 
// as dereferencing a pointer.

void pointer_increment (S & s) { ++s.p; }
  // addq    $4, 32(%rdi)
  // ret

void iterator_increment (S & s) { ++s.i; }
  // addq    $4, 40(%rdi)
  // ret

// Conclusion: Incrementing a vector iterator is the same damn thing as 
// incrementing a pointer.

Catatan: Jika Anda mengalokasikan array dengan newdan mengalokasikan objek non-kelas (seperti polos int) atau kelas tanpa konstruktor yang ditentukan pengguna dan Anda tidak ingin elemen Anda diinisialisasi pada awalnya, menggunakan newarray yang dialokasikan dapat memiliki keunggulan kinerja karena std::vectormenginisialisasi semua elemen ke nilai default (0 untuk int, misalnya) pada konstruksi (kredit ke @bernie untuk mengingatkan saya).

Johannes Schaub - litb
sumber
77
Siapa yang menemukan sintaks AT&T sialan? Hanya jika saya tahu ... :)
Mehrdad Afshari
4
Ini tidak benar untuk kompiler Visual C ++. Tapi untuk GCC itu.
toto
5
Titik dalam jawaban saya adalah bahwa vektor tidak harus lebih lambat daripada operasi pointer correponding. Tentu saja, itu bisa (mudah dicapai dengan mengaktifkan mengaktifkan mode debug juga) :)
Johannes Schaub - litb
18
+1 untuk "Mengindeks vektor sama dengan pengindeksan pointer." dan untuk kesimpulan lainnya juga.
Nawaz
3
@ Piotr99 Saya tidak akan berdebat dengan Anda, tetapi ketika Anda belajar perakitan setelah mempelajari bahasa tingkat yang lebih tinggi, sintaks Intel hanya jauh lebih masuk akal daripada beberapa mundur, diawali (angka), suffix (instruksi), dan tidak jelas (mengakses memori) ) sifat sintaks AT&T.
Cole Johnson
73

Pembukaan untuk orang pengoptimal mikro

Ingat:

"Programer menghabiskan banyak waktu memikirkan, atau mengkhawatirkan, kecepatan bagian nonkritis dari program mereka, dan upaya efisiensi ini sebenarnya memiliki dampak negatif yang kuat ketika debugging dan pemeliharaan dipertimbangkan. Kita harus melupakan efisiensi kecil, katakan tentang 97% dari waktu: optimasi prematur adalah akar dari semua kejahatan. Namun kita tidak boleh melewatkan peluang kita dalam 3% kritis itu ".

(Berkat metamorfosis untuk kutipan lengkapnya)

Jangan gunakan array C alih-alih vektor (atau apa pun) hanya karena Anda percaya itu lebih cepat karena seharusnya tingkat yang lebih rendah. Kamu akan salah

Gunakan dengan vektor default (atau wadah aman disesuaikan dengan kebutuhan Anda), dan kemudian jika profiler Anda mengatakan itu adalah masalah, lihat apakah Anda dapat mengoptimalkannya, baik dengan menggunakan algoritma yang lebih baik, atau mengubah wadah.

Ini mengatakan, kita bisa kembali ke pertanyaan semula.

Statis / Array Dinamis?

Kelas array C ++ berperilaku lebih baik daripada array C tingkat rendah karena mereka tahu banyak tentang diri mereka sendiri, dan dapat menjawab pertanyaan array C tidak bisa. Mereka mampu membersihkan diri mereka sendiri. Dan yang lebih penting, mereka biasanya ditulis menggunakan templat dan / atau inlining, yang berarti bahwa apa yang tampak pada banyak kode dalam debug memutuskan untuk sedikit atau tidak ada kode yang diproduksi dalam rilis rilis, yang berarti tidak ada perbedaan dengan persaingan bawaan yang kurang aman.

Secara keseluruhan, itu jatuh pada dua kategori:

Array dinamis

Menggunakan pointer ke malloc-ed / new-ed array akan lebih baik secepat versi std :: vector, dan jauh lebih tidak aman (lihat posting litb ).

Jadi gunakan std :: vector.

Array statis

Menggunakan array statis adalah yang terbaik:

Jadi gunakan std :: array .

Memori tidak diinisialisasi

Kadang-kadang, menggunakan vectoralih - alih buffer mentah menimbulkan biaya yang terlihat karena vectorakan menginisialisasi buffer pada konstruksi, sedangkan kode yang diganti tidak, seperti dikatakan bernie dalam jawabannya .

Jika ini masalahnya, maka Anda bisa menanganinya dengan menggunakan unique_ptralih - alih vectoratau, jika kasing itu tidak luar biasa dalam codeline Anda, sebenarnya tulislah kelas buffer_owneryang akan memiliki memori itu, dan memberi Anda akses yang mudah dan aman ke sana, termasuk bonus seperti mengubah ukurannya (menggunakan realloc?), atau apa pun yang Anda butuhkan.

paercebal
sumber
1
Terima kasih telah mengatasi array statis juga - std :: vector tidak berguna jika Anda tidak diizinkan untuk mengalokasikan memori secara dinamis untuk alasan kinerja.
Tom
10
Ketika Anda mengatakan "Menggunakan array statis akan paling cepat secepat versi boost :: array" itu menunjukkan seberapa bias Anda. Seharusnya yang lain di sekitar, Boost: array bisa paling cepat seperti array statis.
toto
3
@toto: Ini adalah kesalahpahaman: Anda harus membacanya sebagai "Menggunakan array statis akan menjadi yang terbaik ((secepat dorongan :: versi array) && (jauh lebih sedikit aman))". Saya akan mengedit posting untuk memperjelas ini. Ngomong-ngomong, terima kasih atas manfaat keraguannya.
paercebal
1
bagaimana dengan std :: array?
paulm
4
Selalu perlihatkan kutipan lengkap. "Programer menghabiskan banyak waktu memikirkan, atau mengkhawatirkan, kecepatan bagian nonkritis dari program mereka, dan upaya efisiensi ini sebenarnya memiliki dampak negatif yang kuat ketika debugging dan pemeliharaan dipertimbangkan. Kita harus melupakan efisiensi kecil, katakan tentang 97% dari waktu: optimasi prematur adalah akar dari semua kejahatan. Namun kita tidak boleh melewatkan peluang kita dalam 3% kritis itu. " Kalau tidak, itu menjadi suara yang tidak berarti.
metamorfosis
32

Vektor adalah array di bawah kap. Kinerjanya sama.

Satu tempat di mana Anda dapat mengalami masalah kinerja, tidak mengukur vektor dengan benar untuk memulai.

Sebagai vektor mengisi, itu akan mengubah ukuran sendiri, dan itu bisa menyiratkan, alokasi array baru, diikuti oleh n copy constructor, diikuti oleh tentang n panggilan destructor, diikuti oleh penghapusan array.

Jika konstruk / destruksi Anda mahal, Anda jauh lebih baik membuat vektor ukuran yang benar untuk memulai.

Ada cara sederhana untuk menunjukkan ini. Buat kelas sederhana yang menunjukkan kapan dibangun / dihancurkan / disalin / ditugaskan. Buat vektor hal-hal ini, dan mulailah mendorongnya di bagian belakang vektor. Ketika vektor terisi, akan ada kaskade aktivitas saat ukuran vektor berubah. Kemudian coba lagi dengan ukuran vektor ke jumlah elemen yang diharapkan. Anda akan melihat perbedaannya.

EvilTeach
sumber
4
Pendantry: kinerjanya memiliki O. std :: vektor besar yang sama melakukan sedikit pembukuan, yang mungkin menghabiskan sedikit waktu. OTOH, Anda akhirnya melakukan banyak pembukuan yang sama saat menggulirkan array dinamis Anda sendiri.
dmckee --- ex-moderator kitten
ya saya mengerti. Namun, pertanyaannya adalah apa perbedaan kinerja ..... Saya berusaha mengatasinya.
EvilTeach
Std :: vektor Gcc memang meningkatkan kapasitas satu-per-satu jika Anda memanggil push_back.
bjhend
3
@ bjhend Lalu gcc std::vectorkedengarannya standar-tidak sesuai? Saya percaya standar mensyaratkan bahwa vector::push_backkompleksitas konstan diamortisasi, dan peningkatan kapasitas sebesar 1 pada masing push_back- masing akan menjadi kompleksitas n ^ 2 setelah Anda memperhitungkan reallocs. - menganggap semacam peningkatan kapasitas eksponensial push_backdan insert, kegagalan untuk paling banyak reserveakan menyebabkan peningkatan faktor konstan dalam salinan konten vektor. Faktor pertumbuhan vektor 1,5 eksponensial berarti ~ 3x lebih banyak salinan jika Anda gagal reserve().
Yakk - Adam Nevraumont
3
@Bhhend Anda salah. Standar melarang pertumbuhan eksponensial: § 23.2.3 paragraf 16 mengatakan "Tabel 101 mencantumkan operasi yang disediakan untuk beberapa jenis kontainer berurutan tetapi tidak yang lain. Sebuah implementasi harus menyediakan operasi ini untuk semua jenis kontainer yang ditunjukkan dalam kolom" wadah ", dan harus menerapkannya untuk mengambil waktu yang diamortisasi konstan. " (tabel 101 adalah tabel dengan push_back di dalamnya). Sekarang tolong hentikan penyebaran FUD. Tidak ada implementasi arus utama yang melanggar persyaratan ini. Perpustakaan C ++ standar Microsoft tumbuh dengan faktor 1,5x, dan GCC tumbuh dengan faktor 2x.
R. Martinho Fernandes
27

Untuk menanggapi sesuatu yang dikatakan Mehrdad :

Namun, mungkin ada kasus di mana Anda masih membutuhkan array. Saat berinteraksi dengan kode tingkat rendah (mis. Perakitan) atau pustaka lama yang membutuhkan array, Anda mungkin tidak dapat menggunakan vektor.

Tidak benar sama sekali. Vektor terdegradasi dengan baik menjadi array / pointer jika Anda menggunakan:

vector<double> vector;
vector.push_back(42);

double *array = &(*vector.begin());

// pass the array to whatever low-level code you have

Ini berfungsi untuk semua implementasi STL utama. Dalam standar berikutnya, itu akan diperlukan untuk bekerja (meskipun tidak apa-apa hari ini).

Frank Krueger
sumber
1
Standar saat ini mengatakan tidak ada hal seperti itu. Ini tersirat, dan diimplementasikan sebagai penyimpanan kontinu. Tetapi standar hanya mengatakan bahwa itu adalah wadah akses acak (menggunakan iterator). Standar selanjutnya akan eksplisit.
Frank Krueger
1
& * v.begin () hanya menerapkan operator & untuk hasil de-referensi iterator. De-referensi dapat mengembalikan jenis APA SAJA. Menggunakan alamat-operator lagi dapat mengembalikan jenis APA SAJA. Standar tidak mendefinisikan ini sebagai penunjuk ke area memori yang berdekatan.
Frank Krueger
15
Teks standar 1998 asli memang tidak memerlukannya, tetapi ada tambahan pada tahun 2003 yang membahas hal ini, sehingga benar-benar dicakup oleh Standar. herbalutter.wordpress.com/2008/04/07/...
Nemanja Trifunovic
2
C ++ 03 mengatakan secara eksplisit bahwa &v[n] == &v[0] + nvalid disediakan ndalam kisaran ukuran. Paragraf yang berisi pernyataan ini tidak berubah dengan C ++ 11.
bjhend
2
mengapa tidak menggunakan std :: vector :: data ()?
paulm
15

Anda memiliki lebih sedikit alasan untuk menggunakan larik biasa di C ++ 11.

Ada 3 jenis array di alam dari yang tercepat ke yang paling lambat, tergantung pada fitur yang mereka miliki (tentu saja kualitas implementasi dapat membuat segalanya sangat cepat bahkan untuk kasus 3 dalam daftar):

  1. Statis dengan ukuran yang diketahui pada waktu kompilasi. ---std::array<T, N>
  2. Dinamis dengan ukuran yang diketahui saat runtime dan tidak pernah diubah ukurannya. Optimalisasi khas di sini adalah, jika array dapat dialokasikan dalam tumpukan secara langsung. - Tidak tersedia . Mungkin dynarraydi C ++ TS setelah C ++ 14. Di C ada VLA
  3. Dinamis dan dapat diubah ukurannya saat runtime. ---std::vector<T>

Untuk 1. array statis sederhana dengan jumlah elemen tetap, gunakan std::array<T, N>dalam C ++ 11.

Untuk 2 array ukuran tetap yang ditentukan pada saat runtime, tetapi itu tidak akan mengubah ukurannya, ada diskusi di C ++ 14 tetapi telah dipindahkan ke spesifikasi teknis dan akhirnya dibuat dari C ++ 14.

Untuk 3. std::vector<T> biasanya akan meminta memori di heap . Ini dapat memiliki konsekuensi kinerja, meskipun Anda dapat menggunakannya std::vector<T, MyAlloc<T>>untuk memperbaiki situasi dengan pengalokasi khusus. Keuntungan dibandingkan T mytype[] = new MyType[n];adalah bahwa Anda dapat mengubah ukurannya dan itu tidak akan membusuk ke pointer, seperti array biasa.

Gunakan tipe pustaka standar yang disebutkan untuk menghindari array yang membusuk ke pointer . Anda akan menghemat waktu debug dan kinerjanya persis sama dengan array biasa jika Anda menggunakan set fitur yang sama.

Germán Diago
sumber
2
std :: dynarray. Setelah meninjau komentar badan nasional ke n3690, komponen perpustakaan ini dipilih dari kertas kerja C ++ 14 menjadi Spesifikasi Teknis terpisah. Wadah ini bukan bagian dari konsep C ++ 14 pada n3797. dari en.cppreference.com/w/cpp/container/dynarray
Mohamed El-Nakib
1
jawaban yang sangat bagus singkat dan meringkas, namun lebih detail dari apa pun.
Mohamed El-Nakib
6

Pergilah dengan STL. Tidak ada penalti kinerja. Algoritma sangat efisien dan mereka melakukan pekerjaan yang baik dalam menangani jenis detail yang sebagian besar dari kita tidak akan pikirkan.

John D. Cook
sumber
5

STL adalah perpustakaan yang sangat dioptimalkan. Bahkan, disarankan untuk menggunakan STL dalam game di mana kinerja tinggi mungkin diperlukan. Array terlalu rawan kesalahan untuk digunakan dalam tugas sehari-hari. Kompiler hari ini juga sangat cerdas dan benar-benar dapat menghasilkan kode yang sangat baik dengan STL. Jika Anda tahu apa yang Anda lakukan, STL biasanya dapat memberikan kinerja yang diperlukan. Misalnya dengan menginisialisasi vektor ke ukuran yang diperlukan (jika Anda tahu dari awal), Anda pada dasarnya dapat mencapai kinerja array. Namun, mungkin ada kasus di mana Anda masih membutuhkan array. Saat berinteraksi dengan kode tingkat rendah (mis. Perakitan) atau pustaka lama yang membutuhkan array, Anda mungkin tidak dapat menggunakan vektor.

Mehrdad Afshari
sumber
4
mengingat bahwa vektor berdekatan, masih cukup mudah untuk berinteraksi dengan perpustakaan yang membutuhkan array.
Greg Rogers
Ya, tetapi jika Anda ingin mengacaukan hal-hal internal vektor, akan ada sedikit keuntungan dalam menggunakan vektor. Omong-omong, kata kunci itu "mungkin tidak."
Mehrdad Afshari
3
hanya ada satu case yang saya tahu di mana vektor tidak dapat digunakan: jika ukurannya 0. maka & a [0] atau & * a.begin () tidak akan berfungsi. c ++ 1x akan memperbaikinya dengan memperkenalkan fungsi a.data () yang mengembalikan buffer internal yang menjaga elemen
Johannes Schaub - litb
Skenario khusus dalam pikiran saya ketika saya menulis itu adalah array berbasis stack.
Mehrdad Afshari
1
Interfacing vektor atau wadah yang berdekatan dengan C: vec.data()untuk data dan vec.size()ukuran. Sangat mudah.
Germán Diago
5

Tentang kontribusi duli .

Kesimpulannya adalah bahwa array bilangan bulat lebih cepat daripada vektor bilangan bulat (5 kali dalam contoh saya). Namun, array dan vektor diselubungi dengan kecepatan yang sama untuk data yang lebih kompleks / tidak selaras.

lalebarde
sumber
3

Jika Anda mengkompilasi perangkat lunak dalam mode debug, banyak kompiler tidak akan inline fungsi pengaksesor vektor. Ini akan membuat implementasi vektor stl jauh lebih lambat dalam situasi di mana kinerja merupakan masalah. Ini juga akan membuat kode lebih mudah di-debug karena Anda dapat melihat di debugger berapa banyak memori yang dialokasikan.

Dalam mode yang dioptimalkan, saya berharap vektor stl untuk mendekati efisiensi array. Ini karena banyak metode vektor sekarang digarisbawahi.


sumber
Ini penting untuk disebutkan. Memprofilkan hal STL debug sangat, sangat lambat. Dan itu salah satu alasan mengapa orang menganggap STL lambat.
Erik Aronesty
3

Pasti ada dampak kinerja untuk menggunakan std::vectorvs array mentah ketika Anda ingin buffer tidak diinisialisasi (misalnya untuk digunakan sebagai tujuan memcpy()). Sebuah std::vectorakan menginisialisasi semua elemennya menggunakan konstruktor default. Array mentah tidak akan.

Spesifikasi c ++ untuk std:vectorkonstruktor yang mengambil countargumen (ini bentuk ketiga) menyatakan:

`Membangun sebuah wadah baru dari berbagai sumber data, secara opsional menggunakan alokasi alokasi yang disediakan pengguna.

3) Buat wadah dengan jumlah instance T. yang dimasukkan tidak ada salinan.

Kompleksitas

2-3) Linear dalam hitungan

Array mentah tidak dikenakan biaya inisialisasi ini.

Lihat juga Bagaimana saya bisa menghindari std :: vector <> untuk menginisialisasi semua elemennya?

bernie
sumber
2

Perbedaan kinerja antara keduanya sangat tergantung pada implementasi - jika Anda membandingkan std :: vector yang diimplementasikan dengan buruk dengan implementasi array yang optimal, array akan menang, tetapi balikkan dan vektor akan menang ...

Selama Anda membandingkan apel dengan apel (baik array dan vektor memiliki jumlah elemen tetap, atau keduanya diubah ukurannya secara dinamis), saya akan berpikir bahwa perbedaan kinerja dapat diabaikan selama Anda mengikuti praktik pengkodean STL. Jangan lupa bahwa menggunakan kontainer C ++ standar juga memungkinkan Anda memanfaatkan algoritme pra-linting yang merupakan bagian dari pustaka C ++ standar dan kebanyakan dari mereka cenderung berkinerja lebih baik daripada implementasi rata-rata dari algoritma yang sama yang Anda buat sendiri. .

Yang mengatakan, IMHO vektor menang dalam skenario debug dengan debug STL karena kebanyakan implementasi STL dengan mode debug yang tepat setidaknya dapat menyoroti / menghapus kesalahan khas yang dibuat oleh orang-orang ketika bekerja dengan wadah standar.

Oh, dan jangan lupa bahwa array dan vektor berbagi tata letak memori yang sama sehingga Anda dapat menggunakan vektor untuk meneruskan data ke kode C atau C ++ lama yang mengharapkan array dasar. Perlu diingat bahwa sebagian besar taruhan tidak aktif dalam skenario itu, dan Anda berurusan dengan memori mentah lagi.

Timo Geusch
sumber
1
Saya pikir untuk memenuhi persyaratan kinerja (O (1) pencarian dan penyisipan), Anda hampir harus menerapkan std :: vector <> menggunakan array dinamis. Tentunya ini adalah cara yang jelas untuk melakukannya.
dmckee --- ex-moderator kitten
Tidak hanya persyaratan kinerja, tetapi juga persyaratan penyimpanan yang bersebelahan. Implementasi vektor yang buruk akan menempatkan terlalu banyak lapisan tipuan antara array dan API. Implementasi vektor yang baik akan memungkinkan kode inline, SIMD digunakan pada loop, dll.
Max Lybbert
Implementasi vektor yang buruk seperti yang dijelaskan tidak akan sesuai dengan standar. Jika ingin tipuan, std::dequebisa digunakan.
Phil1970
1

Jika Anda tidak perlu menyesuaikan ukuran secara dinamis, Anda memiliki overhead memori untuk menghemat kapasitas (satu penunjuk / size_t). Itu dia.

Greg Rogers
sumber
1

Mungkin ada beberapa tepi kasus di mana Anda memiliki akses vektor di dalam fungsi inline di dalam fungsi inline, di mana Anda telah melampaui apa yang kompiler akan sebaris dan itu akan memaksa pemanggilan fungsi. Itu akan sangat jarang untuk tidak perlu dikhawatirkan - secara umum saya akan setuju dengan litb .

Saya terkejut belum ada yang menyebutkan ini - jangan khawatir tentang kinerja sampai terbukti menjadi masalah, lalu tolok ukur.

Mark tebusan
sumber
1

Saya berpendapat bahwa perhatian utama bukanlah kinerja, tetapi keamanan. Anda dapat membuat banyak kesalahan dengan array (pertimbangkan untuk mengubah ukuran, misalnya), di mana vektor akan menghemat banyak rasa sakit.

Gabriel Isenberg
sumber
1

Vektor menggunakan sedikit lebih banyak memori daripada array karena mengandung ukuran array. Mereka juga meningkatkan ukuran hard disk program dan mungkin jejak memori program. Peningkatan ini kecil, tetapi mungkin penting jika Anda bekerja dengan sistem tertanam. Meskipun sebagian besar tempat di mana perbedaan ini penting adalah tempat di mana Anda akan menggunakan C daripada C ++.

Brian
sumber
2
Jika ini penting, maka Anda jelas tidak menggunakan array berukuran dinamis, dan karena itu, array Anda tidak perlu mengubah ukuran. (Jika ya, Anda akan menyimpan ukurannya entah bagaimana). Oleh karena itu, Anda sebaiknya menggunakan boost :: array kecuali saya salah - dan apa yang membuat Anda mengatakan bahwa itu perlu "menyimpan ukuran" di suatu tempat?
Arafangion
1

Tes sederhana berikut:

C ++ Array vs Vektor penjelasan tes kinerja

bertentangan dengan kesimpulan dari "Perbandingan kode assembly yang dihasilkan untuk pengindeksan dasar, dereferencing, dan operasi kenaikan pada vektor dan array / pointer."

Harus ada perbedaan antara array dan vektor. Tes mengatakan begitu ... coba saja, kodenya ada ...

Hamed100101
sumber
1

Terkadang array memang lebih baik daripada vektor. Jika Anda selalu memanipulasi set objek dengan panjang tetap, array lebih baik. Pertimbangkan cuplikan kode berikut:

int main() {
int v[3];
v[0]=1; v[1]=2;v[2]=3;
int sum;
int starttime=time(NULL);
cout << starttime << endl;
for (int i=0;i<50000;i++)
for (int j=0;j<10000;j++) {
X x(v);
sum+=x.first();
}
int endtime=time(NULL);
cout << endtime << endl;
cout << endtime - starttime << endl;

}

di mana versi vektor X adalah

class X {
vector<int> vec;
public:
X(const vector<int>& v) {vec = v;}
int first() { return vec[0];}
};

dan versi array X adalah:

class X {
int f[3];

public:
X(int a[]) {f[0]=a[0]; f[1]=a[1];f[2]=a[2];}
int first() { return f[0];}
};

Versi array akan main () akan lebih cepat karena kita menghindari overhead "baru" setiap kali di loop dalam.

(Kode ini telah diposting ke comp.lang.c ++ oleh saya).

Duli
sumber
1

Jika Anda menggunakan vektor untuk mewakili perilaku multidimensi, ada hit kinerja.

Apakah vektor 2d + menyebabkan hit kinerja?

Intinya adalah bahwa ada sejumlah kecil overhead dengan masing-masing sub-vektor memiliki informasi ukuran, dan tidak harus ada serialisasi data (seperti ada dengan array c multi-dimensi). Kurangnya serialisasi ini dapat menawarkan peluang optimasi yang lebih besar daripada mikro. Jika Anda melakukan array multi-dimensi, mungkin yang terbaik adalah hanya memperpanjang std :: vector dan gulung fungsi bit get / set / resize Anda sendiri.

Seph Reed
sumber
0

Dengan asumsi array panjang tetap (misalnya int* v = new int[1000];vs std::vector<int> v(1000);, dengan ukuran vtetap tetap pada 1000), satu-satunya pertimbangan kinerja yang benar-benar penting (atau setidaknya penting bagi saya ketika saya berada dalam dilema yang sama) adalah kecepatan akses ke elemen. Saya mencari kode vektor STL, dan inilah yang saya temukan:

const_reference
operator[](size_type __n) const
{ return *(this->_M_impl._M_start + __n); }

Fungsi ini pasti akan digarisbawahi oleh kompiler. Jadi, selama satu-satunya hal yang Anda rencanakan vadalah mengakses elemen-elemennya operator[], sepertinya tidak ada perbedaan kinerja yang sesungguhnya.

Subh_b
sumber