Baru - baru ini saya mendapatkan saran untuk menggunakan span<T>
kode saya, atau telah melihat beberapa jawaban di sini di situs yang menggunakan span
- seharusnya semacam wadah. Tapi - saya tidak dapat menemukan hal seperti itu di perpustakaan standar C ++ 17.
Jadi apa yang misterius ini span<T>
, dan mengapa (atau kapan) itu ide yang baik untuk menggunakannya jika itu tidak standar?
std::span
diusulkan pada 2017. Ini berlaku untuk C ++ 17 atau C ++ 20. Juga lihat P0122R5, span: bounds-safe views untuk urutan objek . Apakah Anda benar-benar ingin menargetkan bahasa itu? Ini akan menjadi tahun sebelum kompiler mengejar ketinggalan.gsl::span
daripadastd::span
. Lihat juga jawaban saya di bawah ini.Jawaban:
Apa itu?
A
span<T>
adalah:T
di memori.struct { T * ptr; std::size_t length; }
dengan banyak metode kenyamanan.Sebelumnya dikenal sebagai
array_view
dan bahkan sebelumnya sebagaiarray_ref
.Kapan saya harus menggunakannya?
Pertama, kapan tidak menggunakannya:
std::sort
,std::find_if
,std::copy
dan semua fungsi-fungsi templated super-generik.Sekarang kapan benar-benar menggunakannya:
Mengapa saya harus menggunakannya? Mengapa ini hal yang baik?
Oh, bentang luar biasa! Menggunakan
span
...berarti bahwa Anda dapat bekerja dengan kombinasi pointer + length / start + end pointer seperti yang Anda lakukan dengan kontainer perpustakaan standar yang mewah, pimped-out, misalnya:
for (auto& x : my_span) { /* do stuff */ }
std::find_if(my_span.begin(), my_span.end(), some_predicate);
... tetapi sama sekali tidak ada biaya overhead dari sebagian besar kelas kontainer.
memungkinkan kompiler melakukan lebih banyak pekerjaan untuk Anda kadang-kadang. Sebagai contoh, ini:
menjadi ini:
... yang akan melakukan apa yang Anda inginkan. Lihat juga Pedoman H.5 .
adalah alternatif yang masuk akal untuk beralih
const vector<T>&
ke fungsi saat Anda berharap data Anda bersebelahan dalam memori. Tidak ada lagi dimarahi oleh guru C ++ tinggi-dan-perkasa!span
metode akan memiliki beberapa kode pemeriksaan batas dalam#ifndef NDEBUG
...#endif
)Bahkan ada lebih banyak motivasi untuk menggunakan
span
s, yang dapat Anda temukan di pedoman inti C ++ - tetapi Anda mengetahui maksudnya.Mengapa tidak ada di perpustakaan standar (pada C ++ 17)?
Itu ada di perpustakaan standar - tetapi hanya pada C ++ 20. Alasannya adalah bahwa itu masih cukup baru dalam bentuk saat ini, disusun dalam hubungannya dengan pedoman inti C ++ proyek , yang baru mulai terbentuk sejak tahun 2015. (Meskipun sebagai komentator menunjukkan, itu memiliki sejarah sebelumnya.)
Jadi bagaimana cara menggunakannya jika belum ada di perpustakaan standar?
Ini bagian dari Perpustakaan Dukungan Pedoman Inti (GSL). Implementasi:
gsl/span
span<T>
.Implementasi GSL umumnya mengasumsikan platform yang mengimplementasikan dukungan C ++ 14 [ 14 ]. Implementasi single-header alternatif ini tidak bergantung pada fasilitas GSL:
martinmoene/span-lite
membutuhkan C ++ 98 atau lebih barutcbrindle/span
membutuhkan C ++ 11 atau lebih baruPerhatikan bahwa implementasi rentang yang berbeda ini memiliki beberapa perbedaan dalam metode / fungsi pendukung apa yang mereka gunakan; dan mereka juga agak berbeda dari versi yang masuk ke library standar di C ++ 20.
Bacaan lebih lanjut: Anda dapat menemukan semua detail dan pertimbangan desain dalam proposal resmi terakhir sebelum C ++ 17, P0122R7: span: bounds-safe views untuk urutan objek oleh Neal Macintosh dan Stephan J. Lavavej. Tapi agak lama. Juga, di C ++ 20, semantik perbandingan rentang berubah (mengikuti makalah singkat ini oleh Tony van Eerd).
sumber
std::cout << sizeof(buffer) << '\n'
dan Anda akan melihat Anda mendapatkan 100 sizeof (int).std::array
adalah sebuah wadah, ia memiliki nilai.span
tidak memilikistd::array
adalah binatang yang sama sekali berbeda. Panjangnya ditetapkan pada waktu kompilasi dan itu adalah tipe nilai daripada tipe referensi, seperti yang dijelaskan Caleth.@einpoklum melakukan pekerjaan yang cukup baik untuk memperkenalkan apa yang
span
ada dalam jawabannya di sini . Namun, bahkan setelah membaca jawabannya, mudah bagi orang baru untuk melakukan rentang untuk masih memiliki serangkaian pertanyaan yang tidak terjawab sepenuhnya, seperti berikut:span
perbedaan dari array C? Mengapa tidak menggunakan salah satunya saja? Sepertinya itu hanya salah satu dari mereka dengan ukuran yang dikenal juga ...std::array
, bagaimanaspan
bedanya dengan itu?std::vector
sepertistd::array
juga?span
?Jadi, inilah beberapa kejelasan tambahan tentang itu:
KUTIPAN LANGSUNG DARI JAWABANNYA - DENGAN TAMBAHAN SAYA DALAM BOLD :
Bagian yang berani itu penting untuk pemahaman seseorang, jadi jangan sampai ketinggalan atau salah baca! A
span
BUKAN C-array struct, juga bukan merupakan struct dari C-array tipeT
plus panjang array (ini akan menjadi dasarnyastd::array
wadah ), NOR apakah itu bukan C-array struct dari pointer untuk mengetikT
plus panjang, tetapi lebih merupakan struktur tunggal yang berisi satu pointerT
tunggal untuk mengetik , dan panjangnya , yang merupakan jumlah elemen (tipeT
) di blok memori yang berdekatan dimana pointer untuk mengetikT
poin ke! Dengan cara ini, satu-satunya overhead yang telah Anda tambahkan dengan menggunakan aspan
adalah variabel untuk menyimpan pointer dan panjang, dan fungsi aksesor kenyamanan yang Anda gunakanspan
menyediakan.Ini adalah UNLIKE
std::array<>
karenastd::array<>
sebenarnya mengalokasikan memori untuk seluruh blok yang bersebelahan, dan itu UNLIKEstd::vector<>
karena astd::vector
pada dasarnya hanyastd::array
yang juga tumbuh dinamis (biasanya dua kali lipat) setiap kali mengisi dan Anda mencoba menambahkan sesuatu yang lain ke dalamnya . Sebuahstd::array
adalah tetap dalam ukuran, dan sebuahspan
bahkan tidak mengelola memori dari blok itu menunjuk, itu hanya poin ke blok memori, yang tahu berapa lama blok memori, tahu apa tipe data dalam C-array dalam memori, dan memberikan kemudahan akses atau fungsi untuk bekerja dengan elemen-elemen dalam memori yang berdekatan .Ini adalah bagian dari standar C ++:
std::span
adalah bagian dari standar C ++ pada C ++ 20. Anda dapat membaca dokumentasinya di sini: https://en.cppreference.com/w/cpp/container/span . Untuk melihat cara menggunakan Googleabsl::Span<T>(array, length)
di C ++ 11 atau lebih baru hari ini , lihat di bawah.Deskripsi Ringkasan, dan Referensi Kunci:
std::span<T, Extent>
(Extent
= "jumlah elemen dalam urutan, ataustd::dynamic_extent
jika dinamis". Rentang hanya menunjuk ke memori dan membuatnya mudah diakses, tetapi TIDAK mengelolanya!):std::array<T, N>
(perhatikan ukurannya tetapN
!):std::vector<T>
(secara otomatis tumbuh dalam ukuran sesuai kebutuhan):Bagaimana Saya Dapat Menggunakan
span
C ++ 11 atau lebih baru hari ini ?Google telah membuka sumber pustaka C ++ 11 internal mereka dalam bentuk pustaka "Abseil" mereka. Pustaka ini dimaksudkan untuk menyediakan C ++ 14 hingga C ++ 20 dan di luar fitur yang berfungsi di C ++ 11 dan yang lebih baru, sehingga Anda dapat menggunakan fitur besok, hari ini. Mereka bilang:
Berikut beberapa sumber dan tautan utama:
span.h
header, danabsl::Span<T>(array, length)
kelas templat: https://github.com/abseil/abseil-cpp/blob/master/absl/types/span.h#L189sumber