代码之家  ›  专栏  ›  技术社区  ›  Ismail Marmoush

函数中的返回数组

  •  171
  • Ismail Marmoush  · 技术社区  · 14 年前

    int arr[5] 传递给函数的 fillarr(int arr[]) :

    int fillarr(int arr[])
    {
        for(...);
        return arr;
    }
    
    1. 我将如何使用它,比如说我返回了一个指针,我将如何访问它?
    15 回复  |  直到 10 年前
        1
  •  219
  •   GManNickG    14 年前

    在本例中,数组变量 arr

    int fillarr(int arr[])
    

    只是句法上的糖分。你真的可以用这个替代它,它仍然可以工作:

    int fillarr(int* arr)
    

    因此,在同样的意义上,您希望从函数返回的实际上是指向数组中第一个元素的指针:

    int* fillarr(int arr[])
    

    你仍然可以像使用普通数组一样使用它:

    int main()
    {
      int y[10];
      int *a = fillarr(y);
      cout << a[0] << endl;
    }
    
        2
  •  122
  •   Sarfaraz Nawaz    12 年前

    C++函数不能按值返回C样式数组。最接近的方法是返回指针。此外,参数列表中的数组类型仅转换为指针。

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

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

    使用Boost或C++ 11,通过引用仅是可选的,语法也不那么容易弯曲。

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

    这个 array 模板只生成一个 struct 包含一个C风格的数组,这样您就可以应用面向对象的语义,同时保留数组最初的简单性。

        3
  •  27
  •   cubuspl42    10 年前

    在C++ 11中,可以返回 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;
    }
    
        4
  •  25
  •   Chubsdad    14 年前

    8.3.5美元/8个州-

    函数不应具有数组或函数类型的返回类型,尽管它们可能具有指针或引用类型的返回类型。不应有函数数组,尽管可以有指向函数的指针数组。”

    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);
    }
    
        5
  •  14
  •   SingleNegationElimination    14 年前

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

    这正是你所期望的。好的一面是 std::vector 注意确保一切处理干净。缺点是,如果您的数组很大,它会复制大量数据。实际上,它将数组的每个元素复制两次。首先,它复制向量,以便函数可以将其用作参数。然后它再次复制它以返回给调用者。如果你能自己管理向量,你可以做的事情就容易多了(如果调用者需要将其存储在某种变量中以进行更多计算,它可能会第三次复制它)

    看起来你真正想做的只是填充一个集合。如果您没有返回集合的新实例的特定原因,则不要。我们可以这样做

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

    通过这种方式,可以获得对传递给函数的数组的引用,而不是它的私有副本。调用者将看到您对参数所做的任何更改。如果你想的话,你可以返回一个引用,但这并不是一个好主意,因为这意味着你得到了一些与你所传递的不同的东西。

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

    在大多数情况下,使用 *myArr 与使用纯香草矢量的效果相同。本例还通过添加 const

    所有这些都很好,但是惯用c++很少作为一个整体与集合一起工作。通常,您将在这些集合上使用迭代器。看起来更像这样

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

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

    foo现在“指向”修改的 arr

    它真正好的地方在于,它在向量上的效果与在普通C数组和许多其他类型的集合上的效果一样好

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

    现在看起来非常像这个问题中其他地方给出的普通指针示例。

        6
  •  10
  •   hookenz    14 年前

    int fillarr(int arr[])
    

    实际上被视为:

    int fillarr(int *arr)
    

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

    它并没有真正返回数组。你正在返回一个指向 数组地址。

    但请记住,传入数组时,只传入一个指针。 因此,当您修改数组数据时,实际上是在修改 你已经在外面修改了结果。

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

    我建议您考虑在fillarr函数中输入一个长度,比如 这个。

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

    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.
    

    如果您只想将数组设置为一些默认值,请考虑使用 内置的memset函数。

    比如: 内存集((int*)&arr,5,sizeof(int));

    尽管我在讨论这个话题。你说你在使用C++。看看如何使用stl向量。您的代码可能更健壮。

    http://www.yolinux.com/TUTORIALS/LinuxTutorialC++STL.html

        7
  •  6
  •   Adrian    7 年前

    这是一个相当老的问题,但我要把我的2分钱,因为有很多答案,但没有一个显示所有可能的方法在一个明确和简洁的方式(不确定的简洁位,因为这有点失控)。热释光;博士)。

    我假设OP希望返回传入的数组而不进行复制,这是一种直接传递给调用者的方法,以便传递给另一个函数,从而使代码看起来更漂亮。

    但是,使用这样的数组就是让它衰减为指针,并让编译器处理它 喜欢

    std::vector std::array (不确定是否 大约在2010年被问到这个问题时)。然后可以将对象作为引用传递,而无需复制/移动对象。

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

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

    不过,那看起来很难看,而且很难读。我现在用一些东西来帮助那些在2010年不存在的东西,我也用它来做函数指针:

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

    这会将类型移动到预期的位置,从而 更具可读性。当然,如果您只使用5个元素,那么使用模板是多余的,因此您当然可以硬编码它:

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

    就像我说的,我的 type_t<> 在提出这个问题的时候,这个把戏是行不通的。在那时,最好的方法是在结构中使用类型:

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

    这看起来又很难看了,但至少还是更可读,虽然 typename 当时可能是可选的,这取决于编译器,导致:

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

    当然,你可以指定一个特定的类型,而不是使用我的助手。

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

    那时,自由功能 std::begin() std::end() 不存在,但可以很容易地实现。这将允许以更安全的方式对数组进行迭代,因为它们在C数组上是有意义的,而不是指针。

    至于访问数组,您可以将它传递给另一个采用相同参数类型的函数,也可以为它创建一个别名(这没有多大意义,因为您在该范围中已经有了原始的)。访问数组引用就像访问原始数组一样。

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

    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
    }
    

    总而言之,如果要对数组进行迭代,最好不要让数组衰退为指针。这只是一个坏主意,因为它会阻止编译器保护您免受攻击,并使您的代码更难阅读。除非你有很好的理由不这样做,否则总是试着帮助编译器尽可能长地保存类型。

    编辑

    哦,为了完整性,您可以允许它降级为指针,但这会将数组与其所包含的元素数解耦。这在C/C++中做了很多,通常通过传递数组中的元素数量来减轻。但是,如果您犯了一个错误,并将错误的值传递给元素数,编译器就帮不了您。

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

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

    // 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;
    }
    

    请注意,返回值已丢失其原始类型,并降级为指针。因此,您现在需要自己确保不会溢出阵列。

    std::pair<int*, int*> ,您可以使用它作为开始和结束,并将其传递给其他人,但这样它就不再像数组了。

    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];
    }
    

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

    有趣的是,这和 std::initializer_list

        8
  •  5
  •   Sandeep    12 年前

    要从函数返回数组,让我们在结构中定义该数组; 看起来像这样

    struct Marks{
       int list[5];
    }
    

    typedef struct Marks marks;
    marks marks_list;
    

    我们可以通过以下方式将数组传递给函数并为其赋值:

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

    marks getMarks(){
     return marks_list;
    }
    
        9
  •  3
  •   nada    9 年前

    最简单的方法是通过引用返回它,即使你不写 “&”符号,则自动通过引用返回

         void fillarr(int arr[5])
      {
           for(...);
    
      }
    
        10
  •  2
  •   Daniel    14 年前
    int *fillarr(int arr[])
    

    int *returned_array = fillarr(some_other_array);
    if(returned_array[0] == 3)
        do_important_cool_stuff();
    
        11
  •  1
  •   Shehanmark    4 年前

    因为上述路径是正确的。但我认为,如果我们只是返回一个函数的局部数组变量,有时它会返回垃圾值作为它的元素。

    为了避免这种情况,我必须动态创建数组并继续。就像这样。

    int* func()
    {
      int* Arr = new int[100];
      return Arr;
    }
    
    int main()
    {
      int* ArrResult = func();
      cout << ArrResult[0] << " " << ArrResult[1] << endl;
      return 0;
    } 
    
    
    
    
    
        12
  •  0
  •   Nozama    9 年前
    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))
    
        13
  •  0
  •   dcmorse    7 年前

    https://www.tutorialspoint.com/cplusplus/cpp_return_arrays_from_functions.htm

    C++不允许将整个数组作为参数返回到函数。但是,可以通过指定不带索引的数组名称来返回指向数组的指针。

    1. 如果要从函数返回一维数组,则必须声明一个返回指针的函数,如下例所示:
    int * myFunction()    {
       .
       .
       .
    }
    
    1. C++不提倡将局部变量的地址返回到函数的外部,因此必须将局部变量定义为静态变量。

    将这些规则应用于当前问题,我们可以编写如下程序:

    # 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;
     }
    

    输出为:

    p[0]=0
    p[1]=1
    p[2]=2
    p[3]=3
    p[4]=4
    
        14
  •  0
  •   Alexandr    6 年前

    那么:

    int (*func())
    {
        int *f = new int[10] {1,2,3};
    
        return f;
    }
    
    int fa[10] = { 0 };
    auto func2() -> int (*) [10]
    {
        return &fa;
    }
    
        15
  •  0
  •   Abhishek gaur    6 年前

    实际上,当在函数中传递数组时,指向原始数组的指针将在函数参数中传递,因此对该函数中的数组所做的更改实际上是在原始数组上进行的。

    #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';
    }
    

    运行它,您将看到更改

        16
  •  0
  •   Shaonsani    5 年前

    下面是要解决的这类问题的完整示例

    #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;
    }
    
        17
  •  0
  •   Giovanni Paolin    4 年前

    fillarr(int source[], size_t dimSource, int dest[], size_t dimDest)
    {
    
        if (dimSource <= dimDest)
        {
            for (size_t i = 0; i < dimSource; i++)
            {   
                //some stuff...
            }
        }
        else 
        {
            //some stuff..
        }
    }
    

    或者……用一种更简单的方法(但你必须知道尺寸……):

    fillarr(int source[], int dest[])
    {
        //...
    }
    
        18
  •  -1
  •   Shubham Thakur    4 年前

    #include<iostream>
    using namespace std;
    
    char *func(int n)
    {
       // char a[26]; /*if we use this then an error will occur because you are 
                            //  returning address of a local variable*/
        static char a[26];
        char temp='A'; 
        for(int i=0;i<n;i++)
        {
         a[i]=temp;temp++;
        }
        return a;
    }
    int main()
    {
        int n=26;
        char *p=func(n);
        for(int i=0;i<n;i++)
         cout<<*(p+i)<<" ";
    
       //or you can also print like this
      
        for(int i=0;i<n;i++)
         cout<<p[i]<<" ";    
    
    }
    
        19
  •  -2
  •   Ricardo Fercher    7 年前

            private string[] functionReturnValueArray(string one, string two)
        {
    
            string[] x = {one, two};
    
    
            x[0] = "a";
            x[1] = "b";
    
            return x;
        }
    

    . . . 函数调用:

    string[] y;
    y = functionReturnValueArray(stringOne, stringTwo)