我有一个数组int arr[5],传递给一个函数fillarr(int arr[]):

int fillarr(int arr[])
{
    for(...);
    return arr;
}

我如何返回那个数组? 我将如何使用它,比如我返回了一个指针我将如何访问它?


当前回答

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

其他回答

答案可能取决于您计划如何使用该函数。对于最简单的答案,让我们确定您真正需要的不是数组,而是一个向量。向量很好,因为它看起来很无聊,普通的值可以存储在常规指针中。之后我们将看看其他选择以及为什么你需要它们:

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

This will do exactly what you expect it to do. The upside is that std::vector takes care of making sure everything is handled cleanly. the downside is that this copies a very large amount of data, if your array is large. In fact it copies every element of the array twice. first it copies the vector so that the function can use it as a parameter. then it copies it again to return it to the caller. If you can handle managing the vector yourself, you can do things quite a bit more easily. (it may copy it a third time if the caller needs to store it in a variable of some sort to do more calculation)

看起来您真正要做的只是填充一个集合。如果没有特定的理由返回一个集合的新实例,那么就不要这样做。我们可以这样做

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的开头。

这样做的真正好处是,它在vector和普通C数组以及许多其他类型的集合上工作得同样好

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

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

一个简单而详细的例子,如果我忘记了概念,需要帮助,我可以参考这里。

#include <iostream>
using namespace std;
int *ReturnArray(int arr[], int size)
{
    static int MinMax[2] = {0, 0}; // must use static, else address would be deleted after the return is reached
    MinMax[0] = arr[0];
    MinMax[1] = arr[size - 1];
    return MinMax;
}
int main()

{
    int arr[] = {1, 2, 3};
    int size = sizeof(arr) / sizeof(*arr);
    int *ans;                     // pointer to hold returned array
    ans = ReturnArray(arr, size); // only pointer can receive the return, not an array
    cout << "Min: " << ans[0] << " Max: " << ans[1];
    return 0;
}
int *fillarr(int arr[])

你仍然可以使用结果like

int *returned_array = fillarr(some_other_array);
if(returned_array[0] == 3)
    do_important_cool_stuff();

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

还有:

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

    return f;
}

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