Bagaimana cara mendapatkan std :: vektor pointer ke data mentah?

160

Saya mencoba menggunakan std::vectorsebagai chararray.

Fungsi saya menerima pointer kosong:

void process_data(const void *data);

Sebelumnya saya hanya menggunakan kode ini:

char something[] = "my data here";
process_data(something);

Yang bekerja seperti yang diharapkan.

Tapi sekarang saya perlu dinamika std::vector, jadi saya mencoba kode ini sebagai gantinya:

vector<char> something;
*cut*
process_data(something);

Pertanyaannya adalah, bagaimana cara meneruskan vektor char ke fungsi saya sehingga saya dapat mengakses data mentah vektor (tidak peduli format apa itu - mengapung, dll.)?

Saya mencoba ini:

process_data(&something);

Dan ini:

process_data(&something.begin());

Tapi itu kembali pointer ke data yang omong kosong, dan yang terakhir memberikan peringatan: warning C4238: nonstandard extension used : class rvalue used as lvalue.

Calon
sumber

Jawaban:

238

&somethingmemberi Anda alamat std::vectorobjek, bukan alamat data yang dimilikinya. &something.begin()memberi Anda alamat iterator yang dikembalikan oleh begin()(seperti yang diperingatkan oleh kompiler, ini tidak diizinkan secara teknis karena something.begin()merupakan ekspresi nilai, sehingga alamatnya tidak dapat diambil).

Dengan asumsi wadah memiliki setidaknya satu elemen di dalamnya, Anda perlu mendapatkan alamat elemen awal wadah, yang bisa Anda dapatkan melalui

  • &something[0]atau &something.front()(alamat elemen pada indeks 0), atau

  • &*something.begin()(alamat elemen yang ditunjuk oleh iterator dikembalikan oleh begin()).

Dalam C ++ 11, fungsi anggota baru telah ditambahkan ke std::vector: data(). Fungsi anggota ini mengembalikan alamat elemen awal dalam wadah, sama seperti &something.front(). Keuntungan dari fungsi anggota ini adalah tidak apa-apa untuk menyebutnya bahkan jika wadahnya kosong.

James McNellis
sumber
103
Hati - hati Pentingvector<bool> yang merupakan pengecualian untuk jawaban ini (dan tidak memiliki penyimpanan memori yang berdekatan bools).
Motti
18
Sisi baiknya, tidak banyak yang harus diwaspadai: ketiga metode ini akan gagal dikompilasi std::vector<bool>karena std::vector<bool>memerlukan penggunaan objek proxy dan proxy itu tidak dapat secara implisit dikonversi menjadi bool*. Sebagai solusi untuk ini, jika Anda memang membutuhkan urutan bool, yang terbaik hanya menggunakan a std::vector<char>. @Motti
James McNellis
Benar, waspadalah itu secara umum dan tidak diarahkan sebagai jawaban Anda, karena tidak ada penyimpanan memori yang berdekatan tidak ada cara untuk mendapatkannya.
Motti
7
untuk menjadi komprehensif tetapi terutama untuk .data()- Saya hanya akan berpura-pura saya tidak melihat itu jelek &*iterator: P
underscore_d
2
berapa lama pointer akan kembali dari data()live? Jika vektor tidak pernah diubah ukurannya menjadi lebih besar atau lebih kecil (melalui push_back()atau fungsi lainnya, termasuk reserve), apakah dijamin bahwa pointer akan hidup selama vektor hidup, menunjuk ke tempat yang benar?
johnbakers
81

something.data() akan mengembalikan pointer ke ruang data vektor.

Chris Dodd
sumber
error C2039: 'data' : is not a member of 'std::vector<_Ty>'
Rookie
2
@Ookie: sepertinya Anda menggunakan kompiler rusak - 23.3.6.3 dalam spesifikasi C ++ mendefinisikan vektor :: data. Cobalah mengajukan bug dengan vendor Anda atau dapatkan kompiler yang lebih baik.
Chris Dodd
1
@ Chris Dodd Saya memiliki kesalahan yang sama. Saya menggunakan Visual Studio 2008.
bodacydo
34
@ChrisDodd: vector::data()baru untuk C ++ 11
HighCommander4
Saya menggunakan Visual Studio 2012 dan mereka harus menambahkan vektor :: data () karena saya menggunakannya banyak.
Robert Snyder
12

Sebagai gantinya, ambil pointer ke elemen pertama:

process_data (&something [0]);
Steven Don
sumber
Saya pikir itu akan mengembalikan alamat memori item pertama bahkan tanpa tanda kurung subscript?
Tim
Itu untuk array, bukan untuk vektor.
Steven Don
Ya baru menyadari itu, maaf.
Tim