在C++中返回一个数组

8
假设我有一个数组。
int arr[] = {...};
arr = function(arr);

我有以下函数:

 int& function(int arr[])
 {
//rest of the code
        return arr;
 }

我在这里犯了什么错误?

2
你(或任何开发者)为什么写这么疯狂的代码?:\ - kennytm
@manugupt1:你的意图是将数组作为副本传递给函数吗? - Emile Cormier
11个回答

8
正如其他人所说,有更好的选项,比如STL容器,最有趣的问题是为什么需要将数组返回给已经拥有它的函数。 话虽如此,你不能通过值传递或返回数组,并且需要避免数组退化为指针(见例如这里),可以使用指向它的指针或引用。
int (&f(int (&arr)[3]))[3]
{
    return arr;
}

如果您不想硬编码大小,可以使用模板函数:
template<size_t n>
int (&f(int (&arr)[n]))[n]
{
    return arr;
}

这是一些非常“扭曲”的语法。你能在这里正确使用它,真的很值得赞扬。现在我可以放心地使用typedef了,因为我知道你是如何让编译器理解它的,而不需要... +1 - sehe
假设我想为一个固定大小的数组编写一个getter,并且希望该方法以及引用的数组都是const - 从语法上讲,我该怎么做呢?像这样: int const (&GetArray() const)[ 3 ] { return mArray; }? - Bjoern
@Bjoern: typedef int A[3]; const A m; const A& f() const { return m; } ? - Georg Fritzsche
1
谢谢您实际发布了丑陋的语法,而不仅仅是说它很丑并进行typedef。这样做的一个具体例子非常难找到。 - squeevee

8
 int& function(int arr[])

在这个函数中,arr是一个指针,没有办法将其重新转换为数组。这就像...
int& function(int* arr)

int arr[] = {...};
arr = function(arr);

假设该函数成功返回数组的引用,这仍然无法起作用。您无法对数组进行赋值。最好的情况是将结果绑定到“X个整数数组的引用”(使用typedef,否则语法会变得非常丑陋):
typedef int ten_ints[10];

ten_ints& foo(ten_ints& arr)
{
   //..
   return arr;
}

int main()
{
    int arr[10];
    ten_ints& arr_ref = foo(arr);
}

然而,你的问题中的代码到底是用来实现什么的还不清楚。在函数中对数组所做的任何更改都会对调用者可见,因此没有必要尝试返回该数组或将其赋值回原始数组。
如果你想要一个固定大小的数组,可以进行赋值并按值传递(其中内容被复制),可以使用 std::tr1::array(或 boost::array)。std::vector 也是一种选择,但它是动态数组,因此不是完全等价的。

4

数组的传递和返回语义可能会让人感到困惑。使用std::vector代替。


或者如果可用的话,使用boost :: array。 - Macke
10
虽然这当然是好建议,但它根本没有回答问题。 - Andreas Bonini
@Andreas“我在这里犯了什么错误?” - 没有使用向量的错误。 - anon
2
这显然不是原帖作者问的意思。按照那种推理,我也可以回答:“第二个代码片段中没有正确缩进注释的错误”。 - Andreas Bonini

3
你返回的是一个int的引用,而不是数组的引用。
你需要:
(int*)& function(int arr[])
{
     /// rest of the code
     return arr;
}

尽管有其他人已经提到这一点,但是这并不是一个好的做法。

3
实际上,这会返回一个指向指针的引用,而arr也不是一个数组。 - Georg Fritzsche

3
以下内容看起来没有混乱或误解!
int* returnarray(int a[])
{
    for (unsigned int i = 0; i < 3; i++)
    {
        a[i] *= 2;
    }
    return a;
}

int main(int argc, char* argv[])
{
    int arr[3] = {1,2,3};
    int* p = returnarray(arr);
    for (unsigned int i = 0; i < 3; i++)
    {
        cout << "p[" << i << "] = " << p[i] << endl; 
    }
        cin.get();
        return 0;
}

2
我认为最好的方法是将其作为指向数组的指针返回。以下是一个例子:
{
   ...
   int newLength = 0;
   int* arr2 = ChangeArray(arr, length, newLength);
   ...
   delete[] arr2;
}

int* ChangeArray(int arr[], int length, int& newLength)
{
   // reversing the number - just an example
   int* newArr = new int[length];
   for(int i = 0; i < length; i++)
   {
      newArr[i] = arr[length-i-1];
      newLength++;
   }
   return newArr;
}

1
  • 作为参数的数组实际上是一个指针。如果作为参数给出,数组会自动转换为指针。
  • 在C/C++中,你不能将一个数组赋值给另一个数组。你必须使用memcpy或循环来复制值。
  • 如果函数改变了arr参数,它实际上改变了调用者给出的arr变量的值。这是因为数组实际上是一个指针。所以在调用者中,arr被分配给arr,这在这里是无用的。

0
使用std::vector就像这样。
std::vector<int> function(const std::vector<int>& arr)
{
  return arr;
}

类似于数组

int arr[] = {...};

因为它无法复制自身,所以从函数中返回它是没有用的。


0

如果不必要,就不要使用它。你可以只传递一个数组的引用,例如:

void foo(std::vector<int> &v) {
    for (int i = 0; i < 10; ++ i) {
        v.push_back(i);
    }
}

如果你使用:

std::vector<int> foo() {
    std::vector<int> v;
    for (int i = 0; i < 10; ++ i)
        v.push_back(i);

    return v;
}

将会复制容器,这个过程的成本很高。

顺便提一句:NRVO 可能可以消除这个成本。


0

嗯,arr 和 int* 兼容,但不兼容 int&。你的代码无法编译。也许你想要 return arr[0]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接