Misalkan saya memiliki ukuran std::vector
(sebut saja myVec
) N
. Apa cara paling sederhana untuk membuat vektor baru yang terdiri dari salinan elemen X hingga Y, di mana 0 <= X <= Y <= N-1? Misalnya myVec [100000]
melalui myVec [100999]
dalam ukuran vektor 150000
.
Jika ini tidak dapat dilakukan secara efisien dengan vektor, apakah ada tipe data STL lain yang harus saya gunakan?
Jawaban:
Ini adalah operasi O (N) untuk membangun vektor baru, tetapi sebenarnya tidak ada cara yang lebih baik.
sumber
O(Y-X)
, atau mengatakanO(Z) where Z=Y-X
.vector<T> newVec(myVec.begin() + 100000, myVec.begin() + 101000);
?Cukup gunakan konstruktor vektor.
sumber
operator[]
mengembalikan referensi. Hanya pada titik di mana Anda membaca atau menulis referensi bahwa itu akan menjadi pelanggaran akses. Karena kami tidak melakukan keduanya tetapi sebaliknya mendapatkan alamat, kami belum meminta UB ,.std::vector<T>(input_iterator, input_iterator)
, dalam kasus Andafoo = std::vector<T>(myVec.begin () + 100000, myVec.begin () + 150000);
, lihat misalnya di sinisumber
Hari ini, kami menggunakan
span
s! Jadi, Anda akan menulis:untuk mendapatkan rentang 1000 elemen dari jenis yang sama dengan
myvec
's. Atau bentuk yang lebih singkat:(tapi saya tidak terlalu suka ini, karena arti dari setiap argumen numerik tidak sepenuhnya jelas; dan akan menjadi lebih buruk jika panjang dan start_pos memiliki urutan yang sama besarnya.)
Ngomong-ngomong, ingat bahwa ini bukan salinan, itu hanya tampilan data dalam vektor, jadi hati-hati. Jika Anda ingin salinan yang sebenarnya, Anda dapat melakukan:
Catatan:
gsl
kependekan dari Guidelines Support Library. Untuk informasi lebih lanjut tentanggsl
, lihat: http://www.modernescpp.com/index.php/c-core-guideline-the-guidelines-support-library .gsl
, lihat: https://github.com/Microsoft/GSLspan
. Anda akan menggunakanstd::span
dan#include <span>
bukannya#include <gsl/span>
.std::vector
memiliki trilyun konstruktor, sangat mudah untuk jatuh ke dalam yang Anda tidak ingin gunakan, jadi hati-hati.sumber
cbegin
dancend
hanya untuk prinsip;)std::cbegin
dll bahkan.Jika keduanya tidak akan dimodifikasi (tidak ada penambahan / penghapusan item - memodifikasi yang sudah ada baik-baik saja selama Anda memperhatikan masalah threading), Anda dapat dengan mudah berkeliling
data.begin() + 100000
dandata.begin() + 101000
, dan berpura-pura bahwa itu adalahbegin()
danend()
dari vektor yang lebih kecil.Atau, karena penyimpanan vektor dijamin bersebelahan, Anda bisa dengan mudah memberikan 1000 item array:
Kedua teknik ini membutuhkan waktu konstan, tetapi mengharuskan panjang data tidak meningkat, memicu realokasi.
sumber
Diskusi ini cukup lama, tetapi yang paling sederhana belum disebutkan, dengan inisialisasi daftar :
Ini membutuhkan c ++ 11 atau lebih tinggi.
Contoh penggunaan:
Hasil:
sumber
Anda tidak menyebutkan tipe apa
std::vector<...> myVec
, tetapi jika itu tipe sederhana atau struct / kelas yang tidak menyertakan pointer, dan Anda menginginkan efisiensi terbaik, maka Anda dapat melakukan salinan memori langsung (yang saya pikir akan lebih cepat daripada jawaban lain disediakan). Berikut ini adalah contoh umum untukstd::vector<type> myVec
di manatype
dalam hal ini adalahint
:sumber
std::vector(myVec.begin () + 100000, myVec.begin () + 150000);
, bukankah versi yang lebih lama dari ini menghasilkan perakitan yang persis sama?std::vector<>(iter, iter)
kememmove()
, jika sesuai (jika konstruktor sepele, untuk definisi sepele yang sesuai).memcpy
. Apakah seorangstd::copy
atau konstruktor yang menerima rentang (dua iterator), dan kompiler dan std.library akan berkonspirasi untuk memanggilmemcpy
bila perlu.Anda bisa menggunakannya
insert
sumber
Anda dapat menggunakan salin STL dengan kinerja O (M) ketika M adalah ukuran subvektor.
sumber
newvec.reserve(10100 - 10000);
. Ini jelas merupakan pilihan dan secara teknis itu akan berhasil. Tetapi dari dua yang akan Anda rekomendasikan?Satu-satunya cara untuk memproyeksikan koleksi yang bukan waktu linear adalah melakukannya dengan malas, di mana "vektor" yang dihasilkan sebenarnya adalah subtipe yang mendelegasikan ke koleksi asli. Sebagai contoh,
List#subseq
metode Scala membuat sub-urutan dalam waktu yang konstan. Namun, ini hanya berfungsi jika koleksi tersebut tidak berubah dan jika bahasa yang mendasari olahraga pengumpulan sampah.sumber
Posting ini terlambat hanya untuk orang lain .. Aku yakin koder pertama selesai sekarang. Untuk tipe data sederhana salinan tidak diperlukan, cukup kembali ke metode kode C lama yang baik.
Kemudian berikan pointer p dan len ke apa pun yang membutuhkan subvektor.
notelen pasti !!
len < myVec.size()-start
sumber
Mungkin array_view / span di pustaka GSL adalah pilihan yang baik.
Berikut ini juga implementasi file tunggal: array_view .
sumber
Menyalin elemen dari satu vektor ke yang lain dengan mudah
Dalam contoh ini, saya menggunakan vektor pasangan untuk membuatnya mudah dimengerti
`
'
Seperti yang Anda lihat, Anda dapat dengan mudah menyalin elemen dari satu vektor ke yang lain, jika Anda ingin menyalin elemen dari indeks 10 hingga 16 misalnya maka kita akan menggunakan
dan jika Anda ingin elemen dari indeks 10 ke beberapa indeks dari akhir, maka dalam hal itu
Semoga ini bisa membantu, ingat saja dalam kasus terakhir
v.end()-5 > v.begin()+10
sumber
Namun pilihan lain: Berguna misalnya ketika bergerak antara a
thrust::device_vector
dan athrust::host_vector
, di mana Anda tidak dapat menggunakan konstruktor.Seharusnya juga kompleksitas O (N)
Anda dapat menggabungkan ini dengan kode jawaban teratas
sumber