Saya memiliki array int arr[5]
yang dilewatkan ke fungsi fillarr(int arr[])
:
int fillarr(int arr[])
{
for(...);
return arr;
}
- Bagaimana saya bisa mengembalikan array itu?
- Bagaimana saya menggunakannya, katakanlah saya mengembalikan pointer bagaimana saya akan mengaksesnya?
std::vector
.5
tangan fungsi di dibuang oleh kompiler.Jawaban:
Dalam hal ini, variabel array Anda
arr
sebenarnya dapat diperlakukan sebagai pointer ke awal blok array Anda dalam memori, dengan konversi implisit. Sintaks yang Anda gunakan:Ini semacam gula sintaksis saja. Anda benar-benar bisa menggantinya dengan ini dan itu masih berfungsi:
Jadi dalam arti yang sama, apa yang ingin Anda kembalikan dari fungsi Anda sebenarnya adalah sebuah penunjuk ke elemen pertama dalam array:
Dan Anda masih dapat menggunakannya seperti halnya array normal:
sumber
array
dan&array
dapat dipertukarkan dalam banyak kasus.a
inint a[10]
adalahint[10]
. Yang bisa Anda katakan adalah array "peluruhan" menjadi pointer ke elemen pertama mereka. (Ini adalah konversi array-ke-pointer implisit.) Maka jawaban Anda akan sesuai dengan yang saya lakukan. Jika Anda mengedit jawaban Anda untuk membedakan antara array, konversi array-ke-pointer, dan pointer, saya akan menghapus jawaban saya karena mereka akan memiliki informasi inti yang sama dan Anda yang pertama.Fungsi C ++ tidak dapat mengembalikan array gaya-C dengan nilai. Yang paling dekat adalah mengembalikan pointer. Selanjutnya, jenis array dalam daftar argumen hanya dikonversi ke pointer.
Anda bisa memperbaikinya dengan menggunakan referensi array untuk argumen dan mengembalikan, yang mencegah pembusukan:
Dengan Boost atau C ++ 11, pass-by-reference hanya opsional dan sintaksisnya tidak terlalu melemahkan pikiran:
The
array
Template hanya menghasilkanstruct
mengandung array C-gaya, sehingga Anda dapat menerapkan semantik berorientasi objek belum mempertahankan kesederhanaan asli array.sumber
typedef int array[5]; array& foo();
Tapi Anda bahkan tidak perlu typedef jika Anda peduli untuk menulis ini:int (&foo())[5] { static int a[5] = {}; return a; }
, contoh dalam pertanyaan akan menjadi:int (&foo( int (&a)[5] ))[5] { return a; }
. Sederhana bukan?error: function returning array is not allowed
yang terjadi jika Anda meninggalkan bagian luar di sintaks non-typedef. Untungnya, hari ini saya meninjau aturan kanan-kiri untuk pertanyaan lain dan berhasil membangun hal yang benar ... setelah melihat Anda mengatakan itu mungkin ... sebelum melihat bahwa Anda memberikan kode: vP.Di C ++ 11, Anda dapat kembali
std::array
.sumber
(...) you can consider the array returned arr2, totally another array (...)
$ 8,3 / 8 negara-
"Fungsi tidak akan memiliki tipe pengembalian tipe array atau fungsi, meskipun mereka mungkin memiliki tipe kembali tipe pointer atau referensi untuk hal-hal seperti itu. Tidak akan ada array fungsi, meskipun mungkin ada array pointer ke fungsi."
sumber
int
, bukan array.jawabannya mungkin sedikit tergantung pada bagaimana Anda berencana untuk menggunakan fungsi itu. Untuk jawaban yang paling sederhana, mari kita putuskan bahwa alih-alih sebuah array, apa yang sebenarnya Anda inginkan adalah vektor. Vektor bagus karena tampilan untuk seluruh dunia seperti nilai-nilai biasa yang membosankan yang dapat Anda simpan dalam pointer biasa. Kami akan melihat opsi lain dan mengapa Anda menginginkannya setelah itu:
Ini akan melakukan apa yang Anda harapkan. Keuntungannya adalah
std::vector
memastikan semuanya ditangani dengan baik. downside adalah bahwa ini menyalin sejumlah besar data, jika array Anda besar. Bahkan ia menyalin setiap elemen array dua kali. pertama-tama ia menyalin vektor sehingga fungsinya dapat menggunakannya sebagai parameter. lalu menyalinnya lagi untuk mengembalikannya ke pemanggil. Jika Anda dapat menangani sendiri pengaturan vektor, Anda dapat melakukan sesuatu dengan lebih mudah. (itu dapat menyalinnya untuk ketiga kalinya jika penelepon perlu menyimpannya dalam variabel semacam untuk melakukan perhitungan lebih lanjut)Sepertinya yang benar-benar Anda coba lakukan hanyalah mengisi koleksi. jika Anda tidak memiliki alasan khusus untuk mengembalikan instance baru koleksi, maka jangan. kita bisa melakukannya seperti ini
dengan cara ini Anda mendapatkan referensi ke array yang dilewatkan ke fungsi, bukan salinan pribadi itu. setiap perubahan yang Anda lakukan pada parameter dilihat oleh pemanggil. Anda dapat mengembalikan referensi ke sana jika Anda mau, tetapi itu bukan ide yang bagus, karena itu menyiratkan bahwa Anda mendapatkan sesuatu yang berbeda dari apa yang Anda lewati.
Jika Anda benar-benar membutuhkan instance baru dari koleksi, tetapi ingin menghindarinya di stack (dan semua penyalinan yang melibatkan), Anda perlu membuat semacam kontrak untuk bagaimana instance itu ditangani. cara termudah untuk melakukannya adalah dengan menggunakan smart pointer, yang membuat instance yang direferensikan tetap ada selama ada yang memegangnya. Itu hilang dengan bersih jika keluar dari ruang lingkup. Itu akan terlihat seperti ini.
Untuk sebagian besar, menggunakan
*myArr
karya identik dengan menggunakan vektor vanilla polos. Contoh ini juga mengubah daftar parameter dengan menambahkanconst
kata kunci. Sekarang Anda mendapatkan referensi tanpa menyalinnya, tetapi Anda tidak dapat memodifikasinya, sehingga penelepon tahu itu akan sama dengan sebelum fungsinya sampai.Semua ini membengkak, tetapi c ++ idiomatik jarang bekerja dengan koleksi secara keseluruhan. Lebih normal, Anda akan menggunakan iterator di atas koleksi-koleksi itu. itu akan terlihat lebih seperti ini
Menggunakannya terlihat agak aneh jika Anda tidak terbiasa melihat gaya ini.
foo sekarang 'menunjuk ke' awal yang dimodifikasi
arr
.Apa yang benar-benar baik tentang ini adalah bahwa ia berfungsi sama baiknya pada vektor seperti pada array C biasa dan banyak jenis koleksi lainnya, misalnya
Yang sekarang terlihat sangat mirip dengan contoh pointer sederhana yang diberikan di tempat lain dalam pertanyaan ini.
sumber
&
simbol harus muncul setelah jenis:void fillarr(std::vector<int> & arr)
Ini:
sebenarnya diperlakukan sama seperti:
Sekarang jika Anda benar-benar ingin mengembalikan array, Anda dapat mengubah baris itu
Ini tidak benar-benar mengembalikan array. Anda mengembalikan pointer ke awal alamat array.
Tapi ingat ketika Anda memasukkan dalam array, Anda hanya mengirimkan sebuah pointer. Jadi, ketika Anda memodifikasi data array, Anda sebenarnya memodifikasi data yang ditunjuk oleh pointer. Karena itu sebelum Anda melewati array, Anda harus menyadari bahwa Anda sudah memiliki di luar hasil yang dimodifikasi.
misalnya
Saya sarankan Anda mungkin ingin mempertimbangkan untuk memasukkan fungsi fillarr Anda seperti ini.
Dengan begitu Anda bisa menggunakan panjang untuk mengisi panjangnya array, apa pun itu.
Untuk benar-benar menggunakannya dengan benar. Lakukan sesuatu seperti ini:
Jika semua yang ingin Anda lakukan adalah mengatur array ke beberapa nilai default, pertimbangkan untuk menggunakan fungsi memset bawaan.
sesuatu seperti: memset ((int *) & arr, 5, sizeof (int));
Meskipun saya pada topik. Anda mengatakan Anda menggunakan C ++. Lihatlah menggunakan stl vektor. Kode Anda cenderung lebih kuat.
Ada banyak tutorial. Ini adalah salah satu yang memberi Anda ide tentang cara menggunakannya. http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html
sumber
std::copy
atasmemset
, lebih aman dan lebih mudah. (Dan sama cepatnya jika tidak lebih cepat.)untuk mengembalikan array dari suatu fungsi, mari kita mendefinisikan array itu dalam suatu struktur; Jadi terlihat seperti ini
Sekarang mari kita buat variabel dari struktur tipe.
Kita bisa meneruskan array ke suatu fungsi dengan cara berikut dan memberikan nilai padanya:
Kami juga dapat mengembalikan array. Untuk mengembalikan array, tipe pengembalian fungsi harus tipe struktur yaitu tanda. Ini karena pada kenyataannya kita melewati struktur yang berisi array. Jadi kode akhir mungkin terlihat seperti ini.
sumber
Ini adalah pertanyaan yang cukup lama, tapi saya akan memasukkan 2 sen saya karena ada banyak jawaban, tetapi tidak ada yang menunjukkan semua metode yang mungkin dengan cara yang jelas dan ringkas (tidak yakin tentang bit ringkas, karena ini mendapat sedikit keluar dari tangan. TL; DR 😉).
Saya berasumsi bahwa OP ingin mengembalikan array yang diteruskan tanpa menyalin karena beberapa cara langsung melewati ini ke pemanggil untuk diteruskan ke fungsi lain untuk membuat kode terlihat lebih cantik.
Namun, menggunakan array seperti ini berarti membiarkannya membusuk menjadi sebuah pointer dan membuat kompiler memperlakukannya seperti sebuah array. Ini dapat menghasilkan bug halus jika Anda memasukkan dalam array seperti, dengan fungsi yang mengharapkan itu akan memiliki 5 elemen, tetapi pemanggil Anda benar-benar melewati beberapa nomor lainnya.
Ada beberapa cara Anda dapat menangani ini dengan lebih baik. Lulus
std::vector
ataustd::array
(tidak yakin apakahstd::array
ada di sekitar 2010 saat pertanyaan diajukan). Anda kemudian dapat melewatkan objek sebagai referensi tanpa menyalin / memindahkan objek.Namun, jika Anda bersikeras bermain dengan array C, maka gunakan template yang akan menyimpan informasi berapa banyak item dalam array.
Kecuali, itu terlihat jelek, dan sangat sulit dibaca. Saya sekarang menggunakan sesuatu untuk membantu dengan apa yang tidak ada pada tahun 2010, yang saya juga gunakan untuk fungsi pointer:
Ini menggerakkan tipe yang diharapkan, menjadikan ini jauh lebih mudah dibaca. Tentu saja, menggunakan templat berlebihan jika Anda tidak akan menggunakan apa pun kecuali 5 elemen, jadi tentu saja Anda dapat membuat kode keras:
Seperti yang saya katakan,
type_t<>
trik saya tidak akan berfungsi pada saat pertanyaan ini diajukan. Yang terbaik yang bisa Anda harapkan saat itu adalah menggunakan tipe dalam sebuah struct:Yang mulai terlihat sangat jelek lagi, tetapi setidaknya masih lebih mudah dibaca, meskipun
typename
mungkin opsional saat itu tergantung pada kompiler, menghasilkan:Dan tentu saja Anda bisa menentukan jenis tertentu, daripada menggunakan pembantu saya.
Saat itu, fungsi
std::begin()
- fungsi gratis danstd::end()
tidak ada, meskipun bisa dengan mudah diimplementasikan. Ini akan memungkinkan iterasi pada array dengan cara yang lebih aman karena masuk akal pada array C, tetapi bukan pointer.Sedangkan untuk mengakses array, Anda bisa meneruskannya ke fungsi lain yang menggunakan tipe parameter yang sama, atau membuat alias untuk itu (yang tidak masuk akal karena Anda sudah memiliki yang asli dalam lingkup itu). Mengakses referensi array sama seperti mengakses array asli.
atau
Untuk meringkas, yang terbaik adalah tidak membiarkan peluruhan array menjadi pointer jika Anda berniat untuk mengulanginya. Itu hanya ide yang buruk karena membuat kompiler tidak melindungi Anda dari menembak diri sendiri dan membuat kode Anda lebih sulit dibaca. Selalu coba dan bantu kompiler membantu Anda dengan menjaga jenisnya selama mungkin kecuali Anda memiliki alasan yang sangat baik untuk tidak melakukannya.
Edit
Oh, dan untuk kelengkapannya, Anda bisa membiarkannya menurun ke sebuah pointer, tetapi ini memisahkan array dari jumlah elemen yang dimilikinya. Ini banyak dilakukan di C / C ++ dan biasanya dikurangi dengan melewatkan sejumlah elemen dalam array. Namun, kompiler tidak dapat membantu Anda jika Anda membuat kesalahan dan memberikan nilai yang salah ke sejumlah elemen.
Alih-alih melewati ukuran, Anda bisa melewati pointer akhir, yang akan menunjuk ke salah satu melewati ujung array Anda. Ini berguna karena membuat untuk sesuatu yang lebih dekat dengan algoritma std, yang mengambil pointer mulai dan akhir, tetapi apa yang Anda kembalikan sekarang hanya sesuatu yang harus Anda ingat.
Atau, Anda dapat mendokumentasikan bahwa fungsi ini hanya akan mengambil 5 elemen dan berharap pengguna fungsi Anda tidak melakukan hal bodoh.
Perhatikan bahwa nilai kembali telah kehilangan tipe aslinya dan diturunkan ke sebuah pointer. Karena itu, Anda sekarang sendirian untuk memastikan bahwa Anda tidak akan membanjiri array.
Anda dapat melewati a
std::pair<int*, int*>
, yang dapat Anda gunakan untuk memulai dan mengakhiri dan menyebarkannya, tetapi kemudian itu benar-benar berhenti terlihat seperti sebuah array.atau
Cukup lucu, ini sangat mirip dengan cara
std::initializer_list
kerjanya (c ++ 11), tetapi mereka tidak bekerja dalam konteks ini.sumber
cara paling sederhana untuk melakukan ini, adalah mengembalikannya dengan referensi, bahkan jika Anda tidak menulis simbol '&', itu secara otomatis dikembalikan dengan referensi
sumber
Anda masih dapat menggunakan hasilnya seperti
sumber
Seperti jalur yang disebutkan di atas benar. Tapi saya pikir jika kita hanya mengembalikan variabel array lokal dari suatu fungsi kadang-kadang mengembalikan nilai-nilai sampah sebagai elemen-elemennya.
untuk menghindari itu saya harus membuat array secara dinamis dan melanjutkan. Yang kira-kira seperti ini.
sumber
sumber
Sumber: https://www.tutorialspoint.com/cplusplus/cpp_return_arrays_from_functions.htm
C ++ tidak memungkinkan untuk mengembalikan seluruh array sebagai argumen ke suatu fungsi. Namun, Anda dapat mengembalikan pointer ke array dengan menentukan nama array tanpa indeks.
Menerapkan aturan-aturan ini pada pertanyaan saat ini, kita dapat menulis program sebagai berikut:
Outputnya adalah:
sumber
dan bagaimana dengan:
sumber
Sebenarnya ketika Anda melewatkan sebuah array di dalam suatu fungsi, pointer ke array asli dilewatkan dalam parameter fungsi dan dengan demikian perubahan yang dibuat ke array di dalam fungsi tersebut sebenarnya dibuat pada array asli.
Jalankan dan Anda akan melihat perubahannya
sumber
y
itu sendiri dilewatkan sebagai salinan dari dirinya sendiri, tetapi karena itu adalah pointer, Anda akan langsung beroperasi pada array. Harap edit jawaban Anda.Berikut adalah contoh lengkap dari masalah semacam ini untuk dipecahkan
sumber
Cukup tentukan jenis [] sebagai nilai balik, seperti:
. . . panggilan fungsi:
sumber