在C++中从函数返回数组

3
我正在尝试从一个函数返回一个数组:
#include <iostream>

using namespace std;
int* uni(int *a,int *b)
{
    int c[10];
    int i=0;
    while(a[i]!=-1)
    {
        c[i]=a[i];
        i++;
    }
    for(;i<10;i++)
        c[i]=b[i-5];

    return c;
}
int main()
{
    int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
    int b[5]={1,3,4,3,0};
    int *c=uni(a,b);
    for(int i=0;i<10;i++)
        cout<<c[i]<<" ";
    cout<<"\n";

    return 0;
}

我将两个数组从main()传递到我的uni()函数中。在那里,我创建了一个新的数组c[10],并将其返回到main()。 在我的uni()函数中,我尝试合并两个数组ab中的非负数。

但是我得到了这样的输出。

1 -1078199700 134514080 -1078199656 -1216637148 134519488 134519297 134519488 8 -1078199700 

当我尝试在uni()函数中打印c[10]的值时,它会打印出正确的值。这是为什么呢?难道与堆栈有关吗?因为我尝试搜索我的错误,我在stackoverflow上找到了一些地方,上面说不要在堆栈上分配,但我无法理解它。
如果我全局分配数组,那么一切都将变得非常容易,但如果这样的话,所有东西都必须全局声明吗?我们为什么要担心从函数传递指针?(我在书中有一个章节讲解传递指针)

如果您使用的是C++,请尝试使用标准库容器,例如std::arraystd::vector。来回传递指向C风格数组的指针非常混乱且容易出错。 - tadman
不要这样做,返回一个std::vector或std::array(注意函数返回后你的c[10]已经不存在了) - user2249683
你不能返回原始数组。像tadman建议的那样使用容器(也许是通过引用输出参数)。 - Deduplicator
3个回答

9

毫无疑问,std::vectorstd::array是更好的选择。

但是,为了丰富知识(如果这是学校项目,老师规定“不能使用STL”),另一种避免使用指针的替代方法是将数组包装在结构体中,并返回结构体的实例。

#include <iostream>

using namespace std;
struct myArray
{
   int array[10];
};

myArray uni(int *a,int *b)
{
    myArray c;
    int i=0;
    while(a[i]!=-1)
    {
        c.array[i]=a[i];
        i++;
    }
    for(;i<10;i++)
        c.array[i]=b[i-5];
    return c;
}

int main()
{
    int a[10]={1,3,3,8,4,-1,-1,-1,-1,-1};
    int b[5]={1,3,4,3,0};
    myArray c = uni(a,b);
    for(int i=0;i<10;i++)
        cout << c.array[i] << " ";
    cout << "\n";
    return 0;
}

请注意,该结构体是按值返回的,并且此返回值在 main 中被分配。
您具有返回实例的值语义,加上将复制结构体,包括其中的内部数组。 Live Example

5
你正在返回一个指向本地对象的指针。在函数uni中,变量c是在堆栈上分配的。在该函数的末尾,所有这些内存都被释放,在你的for循环中会得到未定义的结果。
如评论所建议的,std::array或std::vector将为您提供复制构造函数,允许您按值返回对象,就像您试图做的那样。否则,您将不得不采取一些像将输出数组作为参数传递的方法。

复制构造函数在返回值情况下通常不是必需的,也不太可能被调用。 - Shoe
谢谢。我对 std::arraystd::vector 不是很了解,我会尝试阅读相关资料。但是,这是否意味着从函数中返回指针是一件毫无意义的事情呢? - coderzz027
1
你不能返回指向栈分配(本地声明)对象的指针。你可以使用new动态分配一个对象并返回它,或者返回指向在其他位置分配的对象的指针。 - Jay Miller
@Jeffry 复制构造函数可能会被优化掉,但如果您删除复制构造函数,则无法通过值返回对象。 话虽如此,我承认“复制构造函数”是错误的说法,应该说这些类型具有复制语义。 - Jay Miller

4

你正在返回一个指向正在返回语句中被释放的数组的指针。这是悬空指针。这是未定义行为。

使用std::vectorstd::array并通过值返回。有编译器优化可以避免低效率。


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