Saya bertanya-tanya mengapa cbegin
dan cend
diperkenalkan di C ++ 11?
Apa kasus ketika memanggil metode-metode ini membuat perbedaan dari overloads konstanta begin
dan end
?
Saya bertanya-tanya mengapa cbegin
dan cend
diperkenalkan di C ++ 11?
Apa kasus ketika memanggil metode-metode ini membuat perbedaan dari overloads konstanta begin
dan end
?
Sederhana saja. Katakanlah saya punya vektor:
std::vector<int> vec;
Saya mengisinya dengan beberapa data. Lalu saya ingin mendapatkan beberapa iterator untuk itu. Mungkin melewati mereka. Mungkin untuk std::for_each
:
std::for_each(vec.begin(), vec.end(), SomeFunctor());
Di C ++ 03, SomeFunctor
bebas untuk dapat memodifikasi parameter yang didapatnya. Tentu, SomeFunctor
bisa mengambil parameternya berdasarkan nilai atau const&
, tetapi tidak ada cara untuk memastikannya . Bukan tanpa melakukan sesuatu yang konyol seperti ini:
const std::vector<int> &vec_ref = vec;
std::for_each(vec_ref.begin(), vec_ref.end(), SomeFunctor());
Sekarang, kami memperkenalkan cbegin/cend
:
std::for_each(vec.cbegin(), vec.cend(), SomeFunctor());
Sekarang, kami memiliki jaminan sintaksis yang SomeFunctor
tidak dapat memodifikasi elemen-elemen vektor (tentu saja, tanpa menggunakan konstanta). Kami secara eksplisit mendapatkan const_iterator
s, dan karenanya SomeFunctor::operator()
akan dipanggil dengan const int &
. Jika parameter itu diambil sebagai int &
, C ++ akan mengeluarkan kesalahan kompiler.
C ++ 17 memiliki solusi yang lebih elegan untuk masalah ini: std::as_const
. Yah, setidaknya elegan saat menggunakan berbasis rentang for
:
for(auto &item : std::as_const(vec))
Ini hanya mengembalikan a const&
ke objek yang disediakan.
std::cbegin/cend
fungsi gratis seperti yangstd::begin/std::end
ada. Itu adalah pengawasan oleh komite. Jika fungsi-fungsi itu memang ada, itu biasanya akan menjadi cara untuk menggunakannya.std::cbegin/cend
akan ditambahkan dalam C ++ 14. Lihat en.cppreference.com/w/cpp/iterator/beginfor(auto &item : std::as_const(vec))
setara denganfor(const auto &item : vec)
?const
referensi. Nicol memandang wadah sebagai const, jadiauto
menyimpulkanconst
referensi. IMOauto const& item
lebih mudah dan lebih jelas. Tidak jelas mengapastd::as_const()
bagus di sini; Saya bisa melihatnya akan berguna ketika melewati sesuatu yang bukanconst
untuk kode generik di mana kita tidak bisa mengontrol tipe yang digunakan, tetapi dengan range-for
, kita bisa, jadi sepertinya ada noise tambahan di sana.Di luar apa yang dikatakan Nicol Bolas dalam jawabannya , pertimbangkan
auto
kata kunci baru :Dengan
auto
, tidak ada cara untuk memastikan bahwabegin()
mengembalikan operator konstan untuk referensi kontainer tidak konstan. Jadi sekarang Anda lakukan:sumber
const_iterator
hanyalah pengidentifikasi lain. Versi tidak menggunakan pencarian dari typedefs anggota biasadecltype(container)::iterator
ataudecltype(container)::const_iterator
.const_iterator
denganauto
: Menulis fungsi template tambahan yang disebutmake_const
lolos argumen objek.Anggap ini sebagai usecase praktis
Penugasan gagal karena
it
merupakan iterator nonconst. Jika Anda menggunakan cbegin pada awalnya, iterator akan memiliki tipe yang tepat.sumber
Dari http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2004/n1674.pdf :
Mereka memberi contoh ini
Perhatikan bahwa kertas kerja juga menyebutkan template adaptor, yang sekarang telah selesai
std::begin()
danstd::end()
dan juga bekerja dengan array asli. Yang sesuaistd::cbegin()
danstd::cend()
anehnya hilang pada saat ini, tetapi mereka mungkin juga ditambahkan.sumber
Baru saja menemukan pertanyaan ini ... Saya tahu itu sudah menjawab dan itu hanya simpul samping ...
auto const it = container.begin()
adalah tipe yang berbedaauto it = container.cbegin()
perbedaan untuk
int[5]
(menggunakan pointer, yang saya tahu tidak memiliki metode mulai tetapi menunjukkan dengan baik perbedaan ... tetapi akan bekerja di c ++ 14 untukstd::cbegin()
danstd::cend()
, yang pada dasarnya apa yang harus digunakan ketika ada di sini) ...sumber
iterator
danconst_iterator
memiliki hubungan pewarisan dan konversi implisit terjadi jika dibandingkan dengan atau ditugaskan ke jenis lainnya.Menggunakan
cbegin()
dancend()
akan meningkatkan kinerja dalam hal ini.sumber
const
manfaat utama adalah kinerja (yang bukan: itu kode yang secara semantik benar dan aman). Tapi, sementara Anda ada benarnya, (A)auto
membuat itu bukan masalah; (B) dalam berbicara tentang kinerja, Anda melewatkan hal utama yang harus Anda lakukan di sini: cacheend
iterator dengan mendeklarasikan salinannya dalam kondisi awalfor
loop, & bandingkan dengan itu, alih-alih mendapatkan salinan baru dengan nilai untuk setiap iterasi. Itu akan membuat poin Anda lebih baik. : Pconst
pasti dapat membantu mencapai kinerja yang lebih baik, bukan karena beberapa keajaiban dalamconst
kata kunci itu sendiri tetapi karena kompiler dapat mengaktifkan beberapa optimasi jika tahu bahwa data tidak akan dimodifikasi, yang tidak akan mungkin dilakukan sebaliknya. Periksa bit ini dari ceramah Jason Turner untuk contoh langsung tentang ini.const
dapat (hampir secara tidak langsung) mengarah pada manfaat kinerja; kalau-kalau seseorang membaca ini mungkin berpikir "Saya tidak akan repot menambahkanconst
jika kode yang dihasilkan tidak terpengaruh dengan cara apa pun", yang tidak benar.sederhana, cbegin mengembalikan iterator konstan di mana mulai mengembalikan iterator
untuk pemahaman yang lebih baik mari kita ambil dua skenario di sini
skenario 1 :
ini akan berjalan karena di sini iterator saya tidak konstan dan dapat bertambah 5
sekarang mari kita gunakan cbegin dan cend menunjukkan mereka sebagai skenario iterators konstan - 2:
ini tidak akan berhasil, karena Anda tidak dapat memperbarui nilai menggunakan cbegin dan cend yang mengembalikan iterator konstan
sumber