Kembalikan array dalam suatu fungsi

212

Saya memiliki array int arr[5]yang dilewatkan ke fungsi fillarr(int arr[]):

int fillarr(int arr[])
{
    for(...);
    return arr;
}
  1. Bagaimana saya bisa mengembalikan array itu?
  2. Bagaimana saya menggunakannya, katakanlah saya mengembalikan pointer bagaimana saya akan mengaksesnya?
Ismail Marmoush
sumber
46
sebenarnya dalam konteks ini Anda tidak perlu mengembalikan array karena array dilewatkan dengan referensi sehingga setiap perubahan pada elemen di dalam 'arr' akan terlihat di luar fungsi.
BuggerMe
12
mengembalikan array nyaman untuk fungsi chaining.
seand
5
Selama Anda tidak membuat kesalahan dengan membuat array di stack dan mengembalikan pointer ke sana.
detly
2
@ismail: Itu tidak bisa mengembalikan array baru, kecuali array itu dialokasikan secara dinamis. Dan jika itu masalahnya, gunakan std::vector.
GManNickG
4
@BuggerMe: Array tidak dilewati oleh referensi (kecuali jika Anda memintanya dengan sintaks yang lebih lucu), dalam kode, array meluruh menjadi pointer ke elemen pertama dan dilewatkan ke fungsi. Tanda 5tangan fungsi di dibuang oleh kompiler.
David Rodríguez - dribeas

Jawaban:

204

Dalam hal ini, variabel array Anda arrsebenarnya dapat diperlakukan sebagai pointer ke awal blok array Anda dalam memori, dengan konversi implisit. Sintaks yang Anda gunakan:

int fillarr(int arr[])

Ini semacam gula sintaksis saja. Anda benar-benar bisa menggantinya dengan ini dan itu masih berfungsi:

int fillarr(int* arr)

Jadi dalam arti yang sama, apa yang ingin Anda kembalikan dari fungsi Anda sebenarnya adalah sebuah penunjuk ke elemen pertama dalam array:

int* fillarr(int arr[])

Dan Anda masih dapat menggunakannya seperti halnya array normal:

int main()
{
  int y[10];
  int *a = fillarr(y);
  cout << a[0] << endl;
}
Brent Menulis Kode
sumber
45
Untuk memperjelas, bahwa "pernyataan C ++ klasik" salah; array bukan pointer.
GManNickG
25
ingat aturan [i] == * (a + i)
seand
8
@Brent Nash, tidak. sebuah array adalah sebuah array. Pointer ke awal array adalah pointer. Kebetulan kompiler memiliki beberapa gula sintaksis yang melakukan terjemahan untuk Anda dalam beberapa situasi. arraydan &arraydapat dipertukarkan dalam banyak kasus.
Carl Norum
20
@Rent: Tidak. Array adalah tipe miliknya sendiri, ini bukan jenis pointer khusus. Jenis ain int a[10]adalah int[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.
GManNickG
8
@ lihat ingat aturan [i] == * (a + sizeof (a) * i)
Amir
114

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.

int *fillarr( int arr[] ) { // arr "decays" to type int *
    return arr;
}

Anda bisa memperbaikinya dengan menggunakan referensi array untuk argumen dan mengembalikan, yang mencegah pembusukan:

int ( &fillarr( int (&arr)[5] ) )[5] { // no decay; argument must be size 5
    return arr;
}

Dengan Boost atau C ++ 11, pass-by-reference hanya opsional dan sintaksisnya tidak terlalu melemahkan pikiran:

array< int, 5 > &fillarr( array< int, 5 > &arr ) {
    return arr; // "array" being boost::array or std::array
}

The arrayTemplate hanya menghasilkan structmengandung array C-gaya, sehingga Anda dapat menerapkan semantik berorientasi objek belum mempertahankan kesederhanaan asli array.

Potatoswatter
sumber
4
+1 untuk memberi contoh bagaimana sebuah array dapat dilewatkan dengan referensi. Tetapi Anda salah karena Anda tidak bisa mengembalikan array dengan referensi. Sintaks sederhana untuk mencapainya adalah dengan menggunakan typedef: 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?
David Rodríguez - dribeas
@ David: terima kasih, saya mendapat kesalahpahaman dari pesan Comeau error: function returning array is not allowedyang 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.
Potatoswatter
1
Jawaban oleh chubsdad memiliki kutipan yang benar dari standar: Anda tidak dapat mengembalikan array, tetapi Anda dapat mengembalikan referensi atau pointer ke array. Array tidak dapat disalin (sebagai tipe) dan karena itu tidak dapat dikembalikan - yang akan menyiratkan salinan - dan ketika sintaksis hadir, kompiler akan mengubah argumen menjadi pointer.
David Rodríguez - dribeas
3
@ David: Begitulah. Halaman ini menjadi sangat panjang. Tidak pernah ada begitu banyak orang yang secara sukarela menulis begitu banyak fungsi sepele yang mengembalikan array di satu tempat.
Potatoswatter
@Potatoswatter Saya baru mengenal cpp, dapatkah Anda menjelaskan cuplikan kode ke-2 secara terperinci? Saya tidak dapat memecahnya menjadi beberapa bagian demi pemahaman.
KPMG
23

Di C ++ 11, Anda dapat kembali std::array.

#include <array>
using namespace std;

array<int, 5> fillarr(int arr[])
{
    array<int, 5> arr2;
    for(int i=0; i<5; ++i) {
        arr2[i]=arr[i]*2;
    }
    return arr2;
}
cubuspl42
sumber
2
Mengutip OP:(...) you can consider the array returned arr2, totally another array (...)
cubuspl42
22

$ 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."

int (&fn1(int (&arr)[5]))[5]{     // declare fn1 as returning refernce to array
   return arr;
}

int *fn2(int arr[]){              // declare fn2 as returning pointer to array
   return arr;
}


int main(){
   int buf[5];
   fn1(buf);
   fn2(buf);
}
Chubsdad
sumber
7
Fungsi kedua Anda mengembalikan pointer ke int, bukan array.
GManNickG
sekali lagi, mengapa mengembalikan tipe ketika array aktual diperbarui di dalam fungsi? Apakah ini masalah praktik terbaik?
Dan
14

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:

std::vector<int> fillarr( std::vector<int> arr ) {
    // do something
    return arr;
}

Ini akan melakukan apa yang Anda harapkan. Keuntungannya adalah std::vectormemastikan 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

void fillarr(std::vector<int> &  arr) {
    // modify arr
    // don't return anything
}

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.

std::auto_ptr<std::vector<int> > fillarr( const std::vector<int> & arr) {
    std::auto_ptr<std::vector<int> > myArr(new std::vector<int>);
    // do stuff with arr and *myArr
    return myArr;
}

Untuk sebagian besar, menggunakan *myArrkarya identik dengan menggunakan vektor vanilla polos. Contoh ini juga mengubah daftar parameter dengan menambahkan constkata 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

template <class Iterator>
Iterator fillarr(Iterator arrStart, Iterator arrEnd) {
    Iterator arrIter = arrStart;
    for(;arrIter <= arrEnd; arrIter++)
       ;// do something
    return arrStart;
}

Menggunakannya terlihat agak aneh jika Anda tidak terbiasa melihat gaya ini.

vector<int> arr;
vector<int>::iterator foo = fillarr(arr.begin(), arr.end());

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

int arr[100];
int *foo = fillarr(arr, arr+100);

Yang sekarang terlihat sangat mirip dengan contoh pointer sederhana yang diberikan di tempat lain dalam pertanyaan ini.

SingleNegationElimination
sumber
Sintaksnya salah, &simbol harus muncul setelah jenis:void fillarr(std::vector<int> & arr)
David Rodríguez - dribeas
9

Ini:

int fillarr(int arr[])

sebenarnya diperlakukan sama seperti:

int fillarr(int *arr)

Sekarang jika Anda benar-benar ingin mengembalikan array, Anda dapat mengubah baris itu

int * fillarr(int arr[]){
    // do something to arr
    return arr;
}

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

int fillarr(int arr[]){
   array[0] = 10;
   array[1] = 5;
}

int main(int argc, char* argv[]){
   int arr[] = { 1,2,3,4,5 };

   // arr[0] == 1
   // arr[1] == 2 etc
   int result = fillarr(arr);
   // arr[0] == 10
   // arr[1] == 5    
   return 0;
}

Saya sarankan Anda mungkin ingin mempertimbangkan untuk memasukkan fungsi fillarr Anda seperti ini.

int * fillarr(int arr[], int length)

Dengan begitu Anda bisa menggunakan panjang untuk mengisi panjangnya array, apa pun itu.

Untuk benar-benar menggunakannya dengan benar. Lakukan sesuatu seperti ini:

int * fillarr(int arr[], int length){
   for (int i = 0; i < length; ++i){
      // arr[i] = ? // do what you want to do here
   }
   return arr;
}

// then where you want to use it.
int arr[5];
int *arr2;

arr2 = fillarr(arr, 5);

// at this point, arr & arr2 are basically the same, just slightly
// different types.  You can cast arr to a (char*) and it'll be the same.

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

Mat
sumber
Gunakan di std::copyatas memset, lebih aman dan lebih mudah. (Dan sama cepatnya jika tidak lebih cepat.)
GManNickG
5

untuk mengembalikan array dari suatu fungsi, mari kita mendefinisikan array itu dalam suatu struktur; Jadi terlihat seperti ini

struct Marks{
   int list[5];
}

Sekarang mari kita buat variabel dari struktur tipe.

typedef struct Marks marks;
marks marks_list;

Kita bisa meneruskan array ke suatu fungsi dengan cara berikut dan memberikan nilai padanya:

void setMarks(int marks_array[]){
   for(int i=0;i<sizeof(marks_array)/sizeof(int);i++)
       marks_list.list[i]=marks_array[i];
}

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.

marks getMarks(){
 return marks_list;
}
Sandeep
sumber
5

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::vectoratau std::array(tidak yakin apakah std::arrayada di sekitar 2010 saat pertanyaan diajukan). Anda kemudian dapat melewatkan objek sebagai referensi tanpa menyalin / memindahkan objek.

std::array<int, 5>& fillarr(std::array<int, 5>& arr)
{
    // (before c++11)
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }

    // Note the following are for c++11 and higher.  They will work for all
    // the other examples below except for the stuff after the Edit.

    // (c++11 and up)
    for(auto it = std::begin(arr); it != std::end(arr); ++it)
    { /* do stuff */ }

    // range for loop (c++11 and up)
    for(auto& element : arr)
    { /* do stuff */ }

    return arr;
}

std::vector<int>& fillarr(std::vector<int>& arr)
{
    for(auto it = arr.begin(); it != arr.end(); ++it)
    { /* do stuff */ }
    return arr;
}

Namun, jika Anda bersikeras bermain dengan array C, maka gunakan template yang akan menyimpan informasi berapa banyak item dalam array.

template <size_t N>
int(&fillarr(int(&arr)[N]))[N]
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

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:

template <typename T>
using type_t = T;

template <size_t N>
type_t<int(&)[N]> fillarr(type_t<int(&)[N]> arr)
{
    // N is easier and cleaner than specifying sizeof(arr)/sizeof(arr[0])
    for(int* it = arr; it != arr + N; ++it)
    { /* do stuff */ }
    return arr;
}

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:

type_t<int(&)[5]> fillarr(type_t<int(&)[5]> arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

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:

template<typename T>
struct type
{
  typedef T type;
};

typename type<int(&)[5]>::type fillarr(typename type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Yang mulai terlihat sangat jelek lagi, tetapi setidaknya masih lebih mudah dibaca, meskipun typenamemungkin opsional saat itu tergantung pada kompiler, menghasilkan:

type<int(&)[5]>::type fillarr(type<int(&)[5]>::type arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Dan tentu saja Anda bisa menentukan jenis tertentu, daripada menggunakan pembantu saya.

typedef int(&array5)[5];

array5 fillarr(array5 arr)
{
    // Prefer using the compiler to figure out how many elements there are
    // as it reduces the number of locations where you have to change if needed.
    for(int* it = arr; it != arr + sizeof(arr)/sizeof(arr[0]); ++it)
    { /* do stuff */ }
    return arr;
}

Saat itu, fungsi std::begin()- fungsi gratis dan std::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.

void other_function(type_t<int(&)[5]> x) { /* do something else */ }

void fn()
{
    int array[5];
    other_function(fillarr(array));
}

atau

void fn()
{
    int array[5];
    auto& array2 = fillarr(array); // alias. But why bother.
    int forth_entry = array[4];
    int forth_entry2 = array2[4]; // same value as forth_entry
}

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.

// separate size value
int* fillarr(int* arr, size_t size)
{
    for(int* it = arr; it != arr + size; ++it)
    { /* do stuff */ }
    return arr;
}

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.

// separate end pointer
int* fillarr(int* arr, int* end)
{
    for(int* it = arr; it != end; ++it)
    { /* do stuff */ }
    return arr;
}

Atau, Anda dapat mendokumentasikan bahwa fungsi ini hanya akan mengambil 5 elemen dan berharap pengguna fungsi Anda tidak melakukan hal bodoh.

// I document that this function will ONLY take 5 elements and 
// return the same array of 5 elements.  If you pass in anything
// else, may nazal demons exit thine nose!
int* fillarr(int* arr)
{
    for(int* it = arr; it != arr + 5; ++it)
    { /* do stuff */ }
    return arr;
}

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.

std::pair<int*, int*> fillarr(std::pair<int*, int*> arr)
{
    for(int* it = arr.first; it != arr.second; ++it)
    { /* do stuff */ }
    return arr; // if you change arr, then return the original arr value.
}

void fn()
{
    int array[5];
    auto array2 = fillarr(std::make_pair(&array[0], &array[5]));

    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

atau

void other_function(std::pair<int*, int*> array)
{
    // Can be done, but you have the original array in scope, so why bother.
    int fourth_element = array2.first[4];
}

void fn()
{
    int array[5];
    other_function(fillarr(std::make_pair(&array[0], &array[5])));
}

Cukup lucu, ini sangat mirip dengan cara std::initializer_listkerjanya (c ++ 11), tetapi mereka tidak bekerja dalam konteks ini.

Adrian
sumber
3

cara paling sederhana untuk melakukan ini, adalah mengembalikannya dengan referensi, bahkan jika Anda tidak menulis simbol '&', itu secara otomatis dikembalikan dengan referensi

     void fillarr(int arr[5])
  {
       for(...);

  }
nada
sumber
2
int *fillarr(int arr[])

Anda masih dapat menggunakan hasilnya seperti

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();
Daniel
sumber
Saya rasa 'int [] fillarr ...' tidak sah. 'Int * fillarr' adalah apa yang akan Anda gunakan karena kesetaraan array-pointer.
seand
1

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.

int* func()
{
  int* Arr = new int[100];
  return Arr;
}

int main()
{
  int* ArrResult = func();
  cout << ArrResult[0] << " " << ArrResult[1] << endl;
  return 0;
} 



Shehanmark
sumber
0
template<typename T, size_t N>
using ARR_REF = T (&)[N];

template <typename T, size_t N>
ARR_REF<T,N> ArraySizeHelper(ARR_REF<T,N> arr);

#define arraysize(arr) sizeof(ArraySizeHelper(arr))
Nozama
sumber
0

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.

  1. Jika Anda ingin mengembalikan array dimensi tunggal dari suatu fungsi, Anda harus mendeklarasikan fungsi yang mengembalikan pointer seperti dalam contoh berikut:
int * myFunction()    {
   .
   .
   .
}
  1. C ++ tidak menganjurkan untuk mengembalikan alamat variabel lokal ke luar fungsi sehingga Anda harus mendefinisikan variabel lokal sebagai variabel statis.

Menerapkan aturan-aturan ini pada pertanyaan saat ini, kita dapat menulis program sebagai berikut:

# include <iostream>

using namespace std;

int * fillarr( );


int main ()
{

   int *p;

   p = fillarr();

   for ( int i = 0; i < 5; i++ )
       cout << "p[" << i << "] : "<< *(p + i) << endl;

    return 0;
}


int * fillarr( )
{
    static int  arr[5];

    for (int i = 0; i < 5; ++i)
        arr[i] = i;

    return arr;
 }

Outputnya adalah:

p[0]=0
p[1]=1
p[2]=2
p[3]=3
p[4]=4
MAQ
sumber
0

dan bagaimana dengan:

int (*func())
{
    int *f = new int[10] {1,2,3};

    return f;
}

int fa[10] = { 0 };
auto func2() -> int (*) [10]
{
    return &fa;
}
Alexandr
sumber
0

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.

#include <iostream>

using namespace std;

int* func(int ar[])
{
    for(int i=0;i<100;i++) 
        ar[i]=i;
    int *ptr=ar;
    return ptr;
}


int main() {
    int *p;
    int y[100]={0};    
    p=func(y);

    for(int i=0;i<100;i++) 
        cout<<i<<" : "<<y[i]<<'\n';
}

Jalankan dan Anda akan melihat perubahannya

Abhishek gaur
sumber
1
Harap gunakan kata-kata bahasa Inggris yang tepat (Anda akan menggantikan Anda akan) dan hapus frasa kosong seperti "teman".
berteriak
Juga: "maka sebenarnya itu dilewatkan sebagai referensi" salah. Variabel yitu sendiri dilewatkan sebagai salinan dari dirinya sendiri, tetapi karena itu adalah pointer, Anda akan langsung beroperasi pada array. Harap edit jawaban Anda.
berteriak
stackoverflow.com/questions/5573310/... TL; DR "Jadi, kedua bentuk itu identik."
berteriak
Ya itu secara teknis array, Anda benar, tetapi apa yang disalin adalah pointer ke array, bukan array itu sendiri.
berteriak
0

Berikut adalah contoh lengkap dari masalah semacam ini untuk dipecahkan

#include <bits/stdc++.h>
using namespace std;
int* solve(int brr[],int n)
{
sort(brr,brr+n);
return brr;
}

int main()
{
int n;
cin>>n;
int arr[n];
for(int i=0;i<n;i++)
{
    cin>>arr[i];
}
int *a=solve(arr,n);
for(int i=0;i<n;i++)
{
    cout<<a[i]<<endl;
}

return 0;
}
Shaonsani
sumber
-2

Cukup tentukan jenis [] sebagai nilai balik, seperti:

        private string[] functionReturnValueArray(string one, string two)
    {

        string[] x = {one, two};


        x[0] = "a";
        x[1] = "b";

        return x;
    }

. . . panggilan fungsi:

string[] y;
y = functionReturnValueArray(stringOne, stringTwo)
Ricardo Fercher
sumber
5
Ini bukan C ++
Adrian