Apa cara termurah untuk menginisialisasi std::vector
dari array C-style?
Contoh: Di kelas berikut, saya punya vector
, tetapi karena batasan luar, data akan diteruskan sebagai larik gaya-C:
class Foo {
std::vector<double> w_;
public:
void set_data(double* w, int len){
// how to cheaply initialize the std::vector?
}
Jelas, saya bisa menelepon w_.resize()
dan kemudian mengulang elemen, atau menelepon std::copy()
. Apakah ada metode yang lebih baik?
Jawaban:
Jangan lupa bahwa Anda dapat memperlakukan pointer sebagai iterator:
sumber
assign
tentu gratis untuk menggunakannya; setidaknya di VC ++, memang melakukan hal itu.v.end()
iterator menunjuk satu melewati akhir dengan vektor dalam kasus yang sama). Jika Anda mendapatkan penegasan, maka ada sesuatu yang salah di tempat lain.Anda menggunakan kata inisialisasi sehingga tidak jelas apakah ini tugas satu kali atau dapat terjadi beberapa kali.
Jika Anda hanya memerlukan inisialisasi satu kali, Anda dapat meletakkannya di konstruktor dan menggunakan dua konstruktor vektor iterator:
Kalau tidak, gunakan penetapan seperti yang disarankan sebelumnya:
sumber
Anda dapat 'mempelajari' ukuran array secara otomatis:
Semoga Anda dapat mengubah antarmuka ke set_data seperti di atas. Ia masih menerima larik gaya-C sebagai argumen pertamanya. Kebetulan mengambilnya dengan referensi.
Bagaimana itu bekerja
[Pembaruan: Lihat di sini untuk diskusi yang lebih komprehensif tentang mempelajari ukuran]
Ini solusi yang lebih umum:
Ini berfungsi karena array dilewatkan sebagai referensi-ke-an-array. Dalam C / C ++, Anda tidak bisa melewatkan array sebagai fungsi, sebaliknya ia akan membusuk ke sebuah pointer dan Anda kehilangan ukurannya. Namun dalam C ++, Anda bisa meneruskan referensi ke array.
Melewati sebuah array dengan referensi membutuhkan tipe yang tepat. Ukuran array adalah bagian dari tipenya. Ini berarti kita dapat menggunakan parameter template N untuk mempelajari ukurannya bagi kita.
Mungkin lebih sederhana untuk memiliki fungsi ini yang mengembalikan vektor. Dengan optimalisasi kompiler yang berlaku, ini harus lebih cepat daripada yang terlihat.
sumber
return { begin(source_array), end(source_array) };
juga dimungkinkanYah, Pavel sudah dekat, tetapi bahkan ada solusi yang lebih sederhana dan elegan untuk menginisialisasi wadah berurutan dari array gaya ac.
Dalam kasus Anda:
sumber
array
(yang biasanya berarti Anda menyalin dari array global atau lokal (dideklarasikan dalam fungsi saat ini)). Dalam kasus OP, dia menerima pointer dan panjang, dan karena itu tidak tergambar panjang, mereka tidak dapat berubah untuk menerima pointer ke array berukuran atau apa pun, jadistd::end
tidak akan berfungsi.vector
tidak kelebihanoperator()
, jadi ini tidak dapat dikompilasi.std::end
dipanggil pada pointer juga tidak ada gunanya (pertanyaannya meminta untuk menetapkan vektor dari pointer dan variabel panjang yang terpisah). Ini akan meningkatkan jawaban Anda untuk menunjukkan lebih banyak konteks tentang apa yang Anda coba sarankanJawaban umum cepat:
atau pertanyaan khusus:
berdasarkan di atas : Jangan lupa bahwa Anda dapat memperlakukan pointer sebagai iterator
sumber
std::vector<double>::assign
adalah cara untuk pergi, karena itu kode kecil . Tapi bagaimana cara kerjanya, sebenarnya? Bukankah itu mengubah ukuran dan kemudian menyalin? Dalam implementasi MS STL saya menggunakannya tidak persis seperti itu.Saya khawatir tidak ada cara yang lebih cepat untuk menerapkan (re) menginisialisasi Anda
std::vector
.sumber