从 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 程序会使k
在cal
中成为静态的。这在他的精确示例中会起作用,但否则会导致“令人惊讶”的行为永无止境。尽管如此,每当标准 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<int>
替换你的数组,忘记指针
(因为您正在处理值),并且代码将起作用。
【讨论】:
std::vector
(甚至 valarray)在这里并不是真正需要的,但你是对的,不需要指针。
@Johnsyweb 对于他的特定示例,std::vector<int>
是显而易见且正确的解决方案。
在带有初始值列表的 C++11 中,我可能同意你的观点,但“正确”是主观的。例如,我认为my answer 中提供的代码是“正确的” mut 没有使用标准库中的容器。
@Johnsyweb 同意(尽管我会使用 std::begin
和 std::end
)。只要不涉及获取或返回数组的函数(仅迭代器),就可以了。 (或者可能不会:在std::vector<int>
中使用back_inserter
可以避免任何错过目标数组大小的风险。)
@Johnsyweb 在 C++11 之前,您将使用个人工具包中的 begin()
和 end()
。这些不是 C++11 发明的;它只是标准化了每个人已经在做的事情。以上是关于从 C++ 中的函数返回指针的主要内容,如果未能解决你的问题,请参考以下文章