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?


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);

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.


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.


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


14

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

alih-alih yang asli sebagai parameter ke yang baru.


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

-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());

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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.