Apa cara yang benar untuk mengulangi vektor dalam C ++?
Pertimbangkan dua fragmen kode ini, ini berfungsi dengan baik:
for (unsigned i=0; i < polygon.size(); i++) {
sum += polygon[i];
}
dan yang satu ini:
for (int i=0; i < polygon.size(); i++) {
sum += polygon[i];
}
yang menghasilkan warning: comparison between signed and unsigned integer expressions
.
Saya baru di dunia C ++, jadi unsigned
variabelnya terlihat sedikit menakutkan bagi saya dan saya tahu unsigned
variabel bisa berbahaya jika tidak digunakan dengan benar, jadi - apakah ini benar?
.size()
bukan tipeunsigned
aliasunsigned int
. Itu tipestd::size_t
.std::size_t
adalah typedef yang didefinisikan oleh _implementation. Lihat Standar.std::size_t
mungkin setara denganunsigned
dalam implementasi Anda saat ini, tetapi itu tidak relevan. Berpura-pura dapat menghasilkan kode non-portabel dan perilaku yang tidak terdefinisi.std::size_t
dalam praktek. Apakah Anda pikir kami sudah membahas semuanya dalam arus komentar yang mengoceh selama 6 tahun?Jawaban:
Untuk iterasi mundur lihat jawaban ini .
Iterasi ke depan hampir identik. Cukup ganti iterators / swap decrement demi increment. Anda harus memilih iterators. Beberapa orang memberi tahu Anda untuk menggunakan
std::size_t
sebagai tipe variabel indeks. Namun, itu tidak portabel. Selalu gunakansize_type
typedef wadah (Meskipun Anda bisa pergi hanya dengan konversi dalam kasus iterasi maju, itu bisa benar-benar salah sepanjang jalan dalam kasus iterasi berulang ketika menggunakanstd::size_t
, dalam kasusstd::size_t
lebih luas dari apa yang diketikkan darisize_type
) :Menggunakan std :: vector
Menggunakan iterators
Yang penting adalah, selalu gunakan formulir kenaikan awalan untuk iterator yang definisinya tidak Anda ketahui. Itu akan memastikan kode Anda berjalan generik mungkin.
Menggunakan Range C ++ 11
Menggunakan indeks
Menggunakan array
Menggunakan iterators
Menggunakan Range C ++ 11
Menggunakan indeks
Baca di jawaban iterasi mundur apa masalahnya
sizeof
bisa dihasilkan pendekatan ini.sumber
for (auto p : polygon){sum += p;}
Empat tahun berlalu, Google memberi saya jawaban ini. Dengan standar C ++ 11 (alias C ++ 0x ) sebenarnya ada cara baru yang menyenangkan untuk melakukan ini (dengan harga melanggar kompatibilitas mundur):
auto
kata kunci baru . Ini menghemat rasa sakit karena harus secara eksplisit menentukan jenis iterator untuk digunakan (mengulangi jenis vektor lagi), ketika jelas (ke kompiler), jenis mana yang digunakan. Denganv
menjadi milik Andavector
, Anda dapat melakukan sesuatu seperti ini:C ++ 11 melangkah lebih jauh dan memberi Anda sintaks khusus untuk mengulangi koleksi seperti vektor. Ini menghilangkan keharusan menulis hal-hal yang selalu sama:
Untuk melihatnya di program kerja, buat file
auto.cpp
:Saat menulis ini, saat Anda mengompilasi ini dengan g ++ , Anda biasanya perlu mengaturnya agar bekerja dengan standar baru dengan memberikan tanda tambahan:
Sekarang Anda dapat menjalankan contoh:
Harap dicatat bahwa instruksi tentang kompilasi dan menjalankan adalah khusus untuk kompiler gnu c ++ di Linux , program harus platform (dan kompiler) independen.
sumber
for (auto& val: vec)
std::vector<int> v = std::vector<int>();
, atau dapatkah Anda menggunakanstd::vector<int> v;
saja?Dalam kasus khusus dalam contoh Anda, saya akan menggunakan algoritma STL untuk mencapai ini.
Untuk kasus yang lebih umum, tetapi masih cukup sederhana, saya akan membahas:
sumber
Mengenai jawaban Johannes Schaub:
Itu mungkin bekerja dengan beberapa kompiler tetapi tidak dengan gcc. Masalahnya di sini adalah pertanyaan apakah std :: vector :: iterator adalah tipe, variabel (anggota) atau fungsi (metode). Kami mendapatkan kesalahan berikut dengan gcc:
Solusinya menggunakan kata kunci 'typename' seperti yang diceritakan:
sumber
T
argumen templat, dan dengan demikian ekspresistd::vector<T*>::iterator
adalah nama dependen. Agar nama dependen diuraikan sebagai tipe, itu harus diawali dengantypename
kata kunci, seperti yang ditunjukkan oleh diagnostik.Panggilan untuk
vector<T>::size()
mengembalikan nilai tipestd::vector<T>::size_type
, bukan int, int tidak bertanda tangan atau sebaliknya.Juga umumnya iterasi di atas wadah dalam C ++ dilakukan menggunakan iterator , seperti ini.
Di mana T adalah tipe data yang Anda simpan dalam vektor.
Atau menggunakan algoritma iterasi yang berbeda (
std::transform
,std::copy
,std::fill
,std::for_each
dan sebagainya).sumber
Gunakan
size_t
:Mengutip Wikipedia :
sumber
#include <cstddef>
daripada<stddef.h>
atau, lebih buruk, keseluruhan[c]stdlib
, dan gunakanstd::size_t
daripada versi yang tidak memenuhi syarat - dan sama untuk situasi lain di mana Anda memiliki pilihan antara<cheader>
dan<header.h>
.Sedikit sejarah:
Untuk menyatakan apakah suatu angka negatif atau tidak, komputer menggunakan bit 'tanda'.
int
adalah tipe data yang ditandatangani artinya dapat memiliki nilai positif dan negatif (sekitar -2billion hingga 2billion).Unsigned
hanya dapat menyimpan angka positif (dan karena tidak membuang sedikit pun pada metadata, ia dapat menyimpan lebih banyak: 0 hingga sekitar 4 miliar).std::vector::size()
mengembalikan sebuahunsigned
, karena bagaimana mungkin vektor memiliki panjang negatif?Peringatan itu memberi tahu Anda bahwa operan kanan pernyataan ketidaksetaraan Anda dapat menyimpan lebih banyak data daripada yang kiri.
Pada dasarnya jika Anda memiliki vektor dengan lebih dari 2 miliar entri dan Anda menggunakan integer untuk mengindeks ke dalam Anda akan mendapatkan masalah overflow (int akan membungkus kembali sekitar negatif 2 miliar).
sumber
Saya biasanya menggunakan BOOST_FOREACH:
Ini bekerja pada wadah STL, array, string gaya-C, dll.
sumber
Agar lengkap, sintaksis C ++ 11 hanya memungkinkan satu versi lain untuk iterator ( ref ):
Yang juga nyaman untuk iterasi terbalik
sumber
Dalam C ++ 11
Saya akan menggunakan algoritma umum
for_each
untuk menghindari mencari jenis iterator dan ekspresi lambda yang tepat untuk menghindari fungsi / objek bernama ekstra.Contoh "cantik" pendek untuk kasus khusus Anda (dengan asumsi poligon adalah vektor bilangan bulat):
diuji pada: http://ideone.com/i6Ethd
Jangan lupa sertakan: algoritma dan, tentu saja, vektor :)
Microsoft sebenarnya juga merupakan contoh yang bagus untuk ini:
sumber: http://msdn.microsoft.com/en-us/library/dd293608.aspx
sumber
sumber
Yang pertama adalah jenis yang benar, dan benar dalam beberapa hal. (Jika Anda berpikir tentang itu, ukuran tidak pernah bisa kurang dari nol.) Namun, peringatan itu mengejutkan saya sebagai salah satu kandidat yang baik untuk diabaikan.
sumber
i == INT_MAX
, kemudiani++
menyebabkan perilaku yang tidak terdefinisi. Pada titik ini apa pun bisa terjadi.Pertimbangkan apakah Anda perlu mengulangi sama sekali
The
<algorithm>
standar header memberikan kita dengan fasilitas untuk ini:Fungsi lain di pustaka algoritma melakukan tugas-tugas umum - pastikan Anda tahu apa yang tersedia jika Anda ingin menghemat usaha.
sumber
Detail yang tidak jelas tetapi penting: jika Anda mengatakan "untuk (otomatis)" sebagai berikut, Anda mendapatkan salinan objek, bukan elemen sebenarnya:
Untuk memodifikasi elemen-elemen vektor, Anda perlu mendefinisikan iterator sebagai referensi:
sumber
Jika kompiler Anda mendukungnya, Anda bisa menggunakan rentang berbasis untuk untuk mengakses elemen vektor:
Cetakan: 1 2 3. Catatan, Anda tidak dapat menggunakan teknik ini untuk mengubah elemen-elemen vektor.
sumber
Dua segmen kode bekerja sama. Namun, rute unsigned int "benar. Menggunakan tipe int unsigned akan bekerja lebih baik dengan vektor pada saat Anda menggunakannya. Memanggil fungsi size () anggota pada vektor mengembalikan nilai integer yang tidak ditandai, jadi Anda ingin membandingkan variabel "i" dengan nilai tipe sendiri.
Juga, jika Anda masih sedikit gelisah tentang bagaimana "unsigned int" terlihat dalam kode Anda, coba "uint". Ini pada dasarnya adalah versi singkat dari "unsigned int" dan berfungsi persis sama. Anda juga tidak perlu menyertakan header lain untuk menggunakannya.
sumber
Menambahkan ini karena saya tidak dapat menemukannya disebutkan dalam jawaban apa pun: untuk iterasi berbasis indeks, kita dapat menggunakan
decltype(vec_name.size())
yang akan dievaluasistd::vector<T>::size_type
Contoh
sumber