Kami menggunakan tipe Integer mewakili variabel indeks sebagian besar waktu. Tetapi dalam beberapa situasi, kita terpaksa memilih
std::vector<int> vec;
....
for(int i = 0; i < vec.size(); ++i)
....
Ini akan menyebabkan kompiler untuk meningkatkan peringatan bahwa penggunaan campuran variabel yang ditandatangani / tidak ditandatangani. jika saya membuat variabel indeks sebagai for( size_t i = 0; i < vec.size(); i++ )
, (atau an unsigned int
) itu akan memilah masalah.
Ketika datang lebih spesifik untuk menggunakan jenis windows, sebagian besar Windows API berhadapan dengan DWORD (yang diketik lama sebagai unsigned).
Jadi ketika saya menggunakan iterasi yang sama, akan kembali menimbulkan peringatan yang sama. Sekarang jika saya menulis ulang sebagai
DWORD dwCount;
....
for(DWORD i = 0; i < dwCount; ++i)
....
Saya menemukan ini agak aneh. Mungkin masalah dengan persepsi.
Saya setuju bahwa kita seharusnya menggunakan jenis variabel indeks yang sama untuk menghindari masalah rentang dapat terjadi dengan variabel indeks. Misalnya, jika kita menggunakan
_int64 i64Count; //
....
for(_int64 i = 0; i < i64Count; ++i)
....
Tetapi dalam kasus DWORD, atau bilangan bulat tak bertanda, apakah ada masalah dalam penulisan ulang sebagai
for(int i = 0; (size_t)i < vec.size(); ++i)
Bagaimana sebagian besar orang bekerja dengan masalah serupa?
std::size_t
peringkatnya lebih tinggi dari int (atau bahkan panjang). Jika ukuran vektor melebihistd::numeric_limits<int>::max()
, Anda akan menyesal telah menggunakan int.Jawaban:
vektor memiliki typedef yang memberitahu Anda jenis yang benar untuk digunakan: -
Meskipun hampir selalu didefinisikan sebagai size_t tetapi Anda tidak dapat mengandalkan itu
sumber
auto i = 0
? Itu sama sekali tidak membantu,i
menjadi seorangint
.using index_t = std::vector<int>::size_type;
.Gunakan iterator untuk ini, bukan
for
loop.Untuk yang lain, selama tipe variabel memiliki ukuran yang sama,
static_cast
harus berfungsi dengan baik (yaituDWORD
untukint16_t
)sumber
for (std::vector<int>::iterator i = vec.begin(); i != vec.end(); ++i)
adalah rasa sakit untuk menulis. Memilikifor (auto i = vec.begin();...
jauh lebih mudah dibaca. Tentu saja,foreach
juga di C ++ 11.Kasus yang Anda gambarkan adalah salah satu hal yang saya sukai di C ++ juga. Tetapi saya telah belajar untuk hidup dengan itu, baik dengan menggunakan
for( size_t i = 0; i < vec.size(); i++ )
atau
for( int i = 0; i < (int)vec.size(); i++ )
(tentu saja, yang terakhir hanya ketika tidak ada risiko mendapatkan beberapa overflow int).
sumber
Alasannya memperingatkan Anda tentang perbandingan antara yang ditandatangani dan yang tidak ditandatangani adalah karena nilai yang ditandatangani kemungkinan akan dikonversi menjadi tidak ditandatangani, yang mungkin bukan yang Anda harapkan.
Dalam contoh Anda (membandingkan
int
dengansize_t
),int
akan secara implisit dikonversi kesize_t
(kecualiint
entah bagaimana memiliki rentang yang lebih besar darisize_t
). Jadi, jikaint
negatif, kemungkinan akan lebih besar dari nilai yang Anda bandingkan dengan karena sampulnya. Ini tidak akan menjadi masalah jika indeks Anda tidak pernah negatif, tetapi Anda akan tetap mendapatkan peringatan itu.Sebaliknya, gunakan tipe unsigned (seperti
unsigned int
,size_t
, atau, seperti John B merekomendasikan ,std::vector<int>::size_type
) untuk variabel indeks Anda:Berhati-hatilah saat menghitung mundur:
Di atas tidak akan berfungsi karena
i >= 0
selalu benar ketikai
tidak ditandatangani. Sebagai gantinya, gunakan " operator panah " untuk loop yang menghitung mundur:Seperti jawaban lain tunjukkan, Anda biasanya ingin menggunakan iterator untuk melintasi a
vector
. Berikut sintaks C ++ 11:sumber
unsigned int
ukurannya tidak cukup besar.Opsi baru untuk C ++ 11, Anda dapat melakukan hal-hal seperti berikut ini
for(decltype(vec.size()) i = 0; i < vec.size(); ++i) {...}
dan
for(decltype(dWord) i = 0; i < dWord; ++i) {...}
Meskipun ia mengulangi sedikit lebih banyak daripada yang akan dilakukan for-loop dasar, itu tidak terlalu panjang lebar seperti cara pra-'11 menentukan nilai, dan menggunakan pola ini secara konsisten akan bekerja untuk sebagian besar, jika tidak semua, kemungkinan istilah yang Anda inginkan ingin membandingkan, yang membuatnya bagus untuk refactoring kode. Ia bahkan berfungsi untuk kasus sederhana seperti ini:
int x = 3; int final = 32; for(decltype(final) i = x; i < final; ++i)
Selain itu, sementara Anda harus menggunakan
auto
setiap kali Anda mengaturi
ke beberapa nilai cerdas (sepertivec.begin()
),decltype
bekerja ketika Anda menetapkan ke konstan seperti nol, di mana otomatis hanya akan menyelesaikannyaint
karena 0 adalah bilangan bulat integer sederhana.Sejujurnya, saya ingin melihat mekanisme kompiler untuk memperluas
auto
penentuan-tipe untuk loop incrementers untuk melihat nilai yang dibandingkan.sumber
Saya menggunakan gips untuk int, seperti pada
for (int i = 0; i < (int)v.size(); ++i)
. Ya, itu jelek. Saya menyalahkan itu pada desain bodoh dari perpustakaan standar di mana mereka memutuskan untuk menggunakan bilangan bulat bertanda untuk mewakili ukuran. (Untuk .. apa? Perluas rentang satu bit?)sumber
if(v.size()-1 > 0) { ... }
mengembalikan true untuk wadah kosong? Masalahnya adalah bahwa ukuran juga sering digunakan dalam aritmatika, khususnya. dengan wadah berbasis indeks, yang meminta masalah mengingat mereka tidak ditandatangani. Pada dasarnya, menggunakan tipe yang tidak ditandatangani untuk hal lain selain 1) manipulasi bitwise, atau 2) aritmatika modular membutuhkan masalah.if(v.size() > 1) { ... }
karena itu membuat maksudnya lebih jelas, dan sebagai bonus tambahan masalah ditandatangani / tidak ditandatangani menjadi batal), saya melihat bagaimana dalam beberapa kasus tertentu kesesuaian mungkin berguna. Saya berdiri dikoreksi.