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

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

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


当前回答

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

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

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

其他回答

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

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

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

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

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

我使用静态数组,当返回数组时,它不应该抛出错误,因为你正在返回本地变量的地址… 所以现在你可以通过将函数中的任何局部创建的变量设置为静态来发送…因为它作为全局变量....工作

#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]<<" ";    

}