cara cepat untuk menyalin satu vektor ke yang lain

155

Saya lebih suka dua cara:

void copyVecFast(const vec<int>& original)
{
  vector<int> newVec;
  newVec.reserve(original.size());
  copy(original.begin(),original.end(),back_inserter(newVec));
}

void copyVecFast(vec<int>& original)
{

  vector<int> newVec;
  newVec.swap(original); 
}

Bagaimana Anda melakukannya?

gsamaras
sumber
14
Yang kedua memiliki nama yang menyesatkan - karena ini bukan salinan (meskipun cepat).
Anonim

Jawaban:

125

Contoh kedua Anda tidak berfungsi jika Anda mengirim argumen dengan referensi. Apakah yang kamu maksud

void copyVecFast(vec<int> original) // no reference
{

  vector<int> new_;
  new_.swap(original); 
}

Itu akan berhasil, tetapi cara yang lebih mudah adalah

vector<int> new_(original);
rbbond
sumber
Bagus, itu berhasil. Tapi itu tidak berfungsi untuk array vektor: misalnya: vektor <int> A [n];
ABcDexter
8
Itu swap, bukan salinan.
sdd
1
@ SDD - tidak, tidak. Periksa daftar argumen. originaladalah salinan dari argumen fungsi.
rlbond
@rlbond Secara tidak sengaja menurunkan jawaban :(, Bisakah Anda mengedit posting, sehingga saya dapat menghapus downvote dan memberikan upvote?
Shubham Sharma
250

Mereka tidak sama, kan? Satu adalah salinan, yang lain adalah swap . Oleh karena itu nama fungsi.

Favorit saya adalah:

a = b;

Di mana adan badalah vektor.

Daniel Earwicker
sumber
3
Bahkan pendekatannya lewat nilai, kompilator memanggil copy constructor, dan kemudian menukar elemen yang baru dibuat. Itulah sebabnya rlbond menyarankan agar memanggil copy constructor secara langsung untuk mencapai efek yang sama.
David Rodríguez - dribeas
1
Namun, Anda tidak dapat memanggil rlbon tanpa fungsi yang melewati aslinya sebagai val. Jika tidak, yang asli akan dikosongkan. Solusi kedua memastikan bahwa Anda akan selalu memanggil berdasarkan nilai dan karenanya Anda tidak akan kehilangan tanggal dalam vektor asli. (Dengan asumsi transaksi swap dengan pointer)
Eyad Ebrahim
Bukankah itu akan memindahkan elemen b ke a (meninggalkan b dengan ukuran == 0)?
Jonathan.
1
@ Jonathan. Dengan asumsi Anda sedang berbicara tentang a = bmaka tidak. Tugas berarti: amenyamakan btanpa mengubah b. Sebaliknya, std::swap(a, b)akan bertukar isinya (sehingga b's sizeakan sekarang menjadi apa pun yang a' s telah sebelumnya). Anda mungkin memikirkan operasi pemindahan (seperti yang terjadi pada C ++ 11, tetapi tidak dalam penugasan biasa seperti ini). Langkah seperti itu akan meninggalkan bdalam keadaan, ahem, "menarik" - lihat stackoverflow.com/questions/17730689/…
Daniel Earwicker
1
@ Jonathan. Perhatikan double ampersand &&. Versi itu hanya akan digunakan untuk referensi nilai. Ini tidak akan cocok dengan nilai non-const (seperti bpada contoh saya di atas). Anda dapat mengubahnya bmenjadi satu dengan mengatakan a = std::move(b);See en.cppreference.com/w/cpp/language/value_category untuk tingkat kompleksitas yang lebih tinggi.
Daniel Earwicker
74

Ini adalah cara lain yang valid untuk membuat salinan vektor, cukup gunakan konstruktornya:

std::vector<int> newvector(oldvector);

Ini bahkan lebih sederhana daripada menggunakan std::copyuntuk berjalan seluruh vektor dari awal hingga selesai untuk std::back_insertmereka ke dalam vektor baru.

Yang sedang berkata, yang Anda .swap()bukan salinan, melainkan menukar dua vektor. Anda akan memodifikasi dokumen asli agar tidak mengandung apa-apa lagi! Yang bukan salinan.

X-Istence
sumber
Lebih fleksibel bagi saya adalah a = b;karena saya sudah memiliki bidang anggota adan saya hanya perlu menetapkannya dengan nilai baru darib
truthadjustr
20

Jawaban langsung:

  • Gunakan =operator

Kita bisa menggunakan fungsi anggota publik std::vector::operator=wadah std::vectoruntuk menetapkan nilai dari vektor ke yang lain.

  • Gunakan fungsi konstruktor

Selain itu, fungsi konstruktor juga masuk akal. Fungsi konstruktor dengan vektor lain sebagai parameter (misalnya x) membuat wadah dengan salinan setiap elemen dix , dalam urutan yang sama.

Peringatan:

  • Jangan gunakan std::vector::swap

std::vector::swaptidak menyalin vektor ke vektor lain, ia sebenarnya menukar elemen dari dua vektor, seperti namanya. Dengan kata lain, vektor sumber untuk menyalin dari diubah setelah std::vector::swapdisebut, yang mungkin bukan yang Anda harapkan.

  • Salinan dalam atau dangkal?

Jika elemen-elemen dalam vektor sumber menunjuk ke data lain, maka salinan yang dalam kadang-kadang dibutuhkan.

Menurut wikipedia:

Salinan yang dalam, artinya bidang yang ditinjau kembali: alih-alih referensi ke objek yang disalin, objek salinan baru dibuat untuk objek yang dirujuk, dan referensi ke ini ditempatkan di B.

Sebenarnya, saat ini tidak ada cara bawaan di C ++ untuk menyalin secara mendalam. Semua cara yang disebutkan di atas dangkal. Jika salinan yang dalam diperlukan, Anda dapat melintasi vektor dan membuat salinan referensi secara manual. Atau, iterator dapat dipertimbangkan untuk dilintasi. Diskusi tentang iterator berada di luar pertanyaan ini.

Referensi

Halaman std::vectordi cplusplus.com

Jerry Yang
sumber
14

Anda tidak boleh menggunakan swap untuk menyalin vektor, itu akan mengubah vektor "asli".

alih-alih yang asli sebagai parameter ke yang baru.

Raz
sumber
14
new_vector.assign(old_vector.begin(),old_vector.end()); // Method 1
new_vector = old_vector; // Method 2
FaridLU
sumber
-14

Jika vektor SUDAH ada dan Anda hanya ingin menyalin, Anda bisa melakukan ini:

newVec.resize(oldVec.size());
memcpy(&newVec.at(0), &oldVec.at(0), oldVec.size());
sgowd
sumber
1
Tolong jangan memcpy. Juga ini tidak akan berfungsi karena memcpy mengambil ukuran dalam byte. Juga jika vektor lain sudah ada, Anda bisa melakukan newVec = oldVecyang sama dengan salah satu jawaban lainnya.
FDinoff
Ya kamu benar. Saya tidak melihat itu. @FDinoff, meskipun di bawah ini berfungsi, mengapa Anda menyarankan untuk tidak menggunakan memcpy? Tampaknya jauh lebih cepat daripada newVec = oldVec. memcpy (& newVec.at (0), & oldVec.at (0), oldVec.size () * sizeof (int));
sgowd
1
Dalam kasus umum, Menyalin objek tanpa memanggil pembuat konstruksinya dapat menyebabkan bug halus. Dalam hal ini saya akan berpikir mereka akan memiliki kinerja yang sama. Jika tidak, saya akan mengatakan vektor tidak dioptimalkan kinerja, karena seharusnya sudah melakukan ini. Apakah Anda benar-benar menulis patokan?
FDinoff
Saya tidak mengkritik Anda .. Pemimpin tim saya juga menyarankan hal yang sama dan saya berusaha untuk mengerti.
sgowd
(Saya tidak berpikir Anda mengkritik saya.) Apakah masih ada sesuatu yang Anda tidak mengerti?
FDinoff