从 C++ 中的函数返回指针

Posted

技术标签:

【中文标题】从 C++ 中的函数返回指针【英文标题】:Returning Pointer from a Function in C++ 【发布时间】:2012-01-23 09:15:27 【问题描述】:

当我从函数返回指针时,它的值可以单独访问。但是,当使用循环输出该指针变量的值时,会显示错误的值。我在哪里犯错误,无法弄清楚。

#include <iostream>
#include <conio.h>

int *cal(int *, int*);

using namespace std;

int main()

    int a[]=5,6,7,8,9;
    int b[]=0,3,5,2,1;
    int *c;
    c=cal(a,b);

    //Wrong outpur here
    /*for(int i=0;i<5;i++)
    
        cout<<*(c+i);
    */

    //Correct output here
    cout<<*(c+0);
    cout<<*(c+1);
    cout<<*(c+2);
    cout<<*(c+3);
    cout<<*(c+4);

return 0;
   

int *cal(int *d, int *e)

    int k[5];
    for(int j=0;j<5;j++)
    
        *(k+j)=*(d+j)-*(e+j);
    
    return k;

【问题讨论】:

打开编译器警告,然后阅读它们。 很少有(如果有的话)需要从函数返回指针的情况。以我的经验,返回指针的需求通常源于有缺陷的程序设计。大多数情况下,您会通过其中一个参数返回结果,并让调用者担心在哪里分配数据。 @Lundin 有一些值得注意的例外(例如,查找函数可能会失败)。另一方面,只有在绝对必要时才应使用通过其中一个参数返回,当分析器说您别无选择时。大多数时候,正确的解决方案是按值返回。当然,这意味着不使用 C 样式数组(但总的来说这是一个很好的建议)。 SO 上已经有很多重复项,例如Error in returning a pointer from a function that points to an array @Lundin 在 C 中,当然,您的选择要少得多。从历史上看,C 程序会使kcal 中成为静态的。这在他的精确示例中会起作用,但否则会导致“令人惊讶”的行为永无止境。尽管如此,每当标准 C 库必须返回一个指针时,它就是这样做的。 【参考方案1】:

您正在返回一个指向局部变量的指针。

k 在堆栈上创建。当cal() 退出时,堆栈被展开并且内存被释放。之后引用该内存会导致未定义的行为(如此处精美的解释:https://***.com/a/6445794/78845)。

您的 C++ 编译器应该对此发出警告,并且您应该注意这些警告。

对于它的价值,这是我在 C++ 中实现它的方法:

#include <algorithm>
#include <functional>
#include <iostream>
#include <iterator>

int main()

    int a[] = 5, 6, 7, 8, 9;
    int b[] = 0, 3, 5, 2, 1;
    int c[5];
    std::transform (a, a + 5, b, c, std::minus<int>());
    std::copy(c, c + 5, std::ostream_iterator<int>(std::cout, ", "));

See it run!

【讨论】:

@PoweRoy:不应该“可能”被摧毁吗?它不能保证被摧毁,是吗?这肯定是非法访问... @another.anon.coward:它将被销毁,否则 RAII 将无法工作。无法保证是否有其他任何东西使用该内存。 @Johnsyweb:感谢您提供的信息!【参考方案2】:

int k[5] 数组在堆栈上创建。因此,当它从cal 返回超出范围时,它会被销毁。您可以使用第三个参数作为输出数组:

void cal(int *d, int *e, int* k)

    for(int j=0;j<5;j++)
    
        *(k+j)=*(d+j)-*(e+j);
    

像这样拨打cal

int a[]=5,6,7,8,9;
int b[]=0,3,5,2,1;
int c[5];
cal (a, b, c); // after returning from cal, c will be populated with desired values

【讨论】:

您在 void 返回函数中返回一个值! :) 你还在玩原始指针,没必要这么做! @Johnsyweb 我知道这里不需要使用指针。但是如果提问者想使用指针,这就是要走的路:) 也许 OP 想要使用指针,因为不知道有其他方法。我喜欢this Meta answer 中的建议。【参考方案3】:

正如其他人所指出的,您正在返回一个指向本地的指针 变量,这是未定义的行为。然而,真正的问题是 您需要返回一个数组,而 C 样式的数组已损坏。 用std::vector&lt;int&gt; 替换你的数组,忘记指针 (因为您正在处理值),并且代码将起作用。

【讨论】:

std::vector(甚至 valarray)在这里并不是真正需要的,但你是对的,不需要指针。 @Johnsyweb 对于他的特定示例,std::vector&lt;int&gt; 是显而易见且正确的解决方案。 在带有初始值列表的 C++11 中,我可能同意你的观点,但“正确”是主观的。例如,我认为my answer 中提供的代码是“正确的” mut 没有使用标准库中的容器。 @Johnsyweb 同意(尽管我会使用 std::beginstd::end)。只要不涉及获取或返回数组的函数(仅迭代器),就可以了。 (或者可能不会:在std::vector&lt;int&gt; 中使用back_inserter 可以避免任何错过目标数组大小的风险。) @Johnsyweb 在 C++11 之前,您将使用个人工具包中的 begin()end()。这些不是 C++11 发明的;它只是标准化了每个人已经在做的事情。

以上是关于从 C++ 中的函数返回指针的主要内容,如果未能解决你的问题,请参考以下文章

返回后指针不会从函数返回到它的引用(保持为空)C++

函数指针返回具有局部性的 C++ 中的另一个函数指针

从函数 C++ 正确传递指针

C#从返回char指针的c++函数中获取字符串/字符值

从 C 中的函数返回一个 `struct`

C ++从函数返回指向数组的指针的正确方法