首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >C++从函数返回指向数组指针的正确方法

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

Stack Overflow用户
提问于 2012-10-21 05:36:03
回答 7查看 147.2K关注 0票数 30

我是C++的新手,并且一直避免使用指针。根据我在网上读到的内容,我不能返回一个数组,但我可以返回一个指向它的指针。我写了一个小代码来测试它,我想知道这是不是正常/正确的方法:

代码语言:javascript
复制
#include <iostream>
using namespace std;

int* test (int in[5]) {
    int* out = in;
    return out;
}

int main() {
    int arr[5] = {1, 2, 3, 4, 5};
    int* pArr = test(arr);
    for (int i = 0; i < 5; i++) cout<<pArr[i]<<endl;
    cout<<endl;
    return 0;
}

编辑:这似乎不太好。我该怎么重写呢?

代码语言:javascript
复制
int* test (int a[5], int b[5]) {
    int c[5];
    for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
    int* out = c;
    return out;
}
EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2012-10-21 05:54:22

你的代码目前是正确的,但我很难弄清楚它如何在现实世界的场景中使用。话虽如此,但在从函数返回指针时,请注意以下几点:

  • 当您使用语法int arr[5];创建数组时,它是在堆栈上分配的,并且是函数的局部数组。
  • C++允许您返回指向此数组的指针,但在其局部作用域之外使用此指针指向的内存是undefined behavior
  • 如果你能保证数组的内存没有被清除,你仍然可以在作用域之外使用数组。在您的例子中,当您向test().
  • If传递arr时,您希望传递指向动态分配的数组的指针,而不用担心内存泄漏,您应该在std::unique_ptr/std::shared_ptr<>.

上做一些阅读

编辑-回答矩阵乘法的用例

您有两个选择。最简单的方法是使用std::unique_ptr/std::shared_ptr<>。现代的C++方法是使用Matrix类,在该类中重载operator *,如果您想避免复制乘法的结果以将其从函数中取出,则必须使用新的rvalue references。除了你的copy constructoroperator =destructor,你还需要有move constructormove assignment operator。请浏览this search的问答,以便更深入地了解如何实现此目标。

编辑2-附加问题的答案

代码语言:javascript
复制
int* test (int a[5], int b[5]) {
    int *c = new int[5];
    for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
    return c;
}

如果您将它用作int *res = test(a,b);,那么稍后在您的代码中,您应该调用delete []res来释放在test()函数中分配的内存。您现在看到的问题是,手动跟踪何时调用delete是极其困难的。因此,答案中概述了如何处理它的方法。

票数 21
EN

Stack Overflow用户

发布于 2012-10-21 06:00:19

您的代码是正确的。但请注意,如果您返回一个指向数组的指针,并且该数组超出了作用域,则不应再使用该指针。示例:

代码语言:javascript
复制
int* test (void)
{
    int out[5];
    return out;
}

上面的方法永远不会起作用,因为当test()返回时,out将不再存在。不能再使用返回的指针。如果你真的使用它,你将会读/写你不应该使用的内存。

在原始代码中,当main()返回时,arr数组超出了作用域。显然,这不是问题,因为从main()返回也意味着您的程序正在终止。

如果你想要的东西能留下来并且不能超出作用域,你应该用new来分配它

代码语言:javascript
复制
int* test (void)
{
    int* out = new int[5];
    return out;
}

返回的指针将始终有效。但请记住,使用完它后,请使用delete[]再次删除它

代码语言:javascript
复制
int* array = test();
// ...
// Done with the array.
delete[] array;

删除它是回收它使用的内存的唯一方法。

票数 17
EN

Stack Overflow用户

发布于 2012-10-21 06:09:14

新问题的新答案:

不能从函数返回指向自动变量(int c[5])的指针。自动变量以返回封闭块(在本例中为函数)结束其生命周期-因此返回的指针不是现有的数组。

要么将变量设置为动态变量:

代码语言:javascript
复制
int* test (int a[5], int b[5]) {
    int* c = new int[5];
    for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
    return c;
}

或者更改您的实现以使用std::array

代码语言:javascript
复制
std::array<int,5> test (const std::array<int,5>& a, const std::array<int,5>& b) 
{
   std::array<int,5> c;
   for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
   return c;
}

如果您的编译器没有提供std::array,您可以将其替换为包含数组的简单结构:

代码语言:javascript
复制
struct array_int_5 { 
   int data[5];
   int& operator [](int i) { return data[i]; } 
   int operator const [](int i) { return data[i]; } 
};

老问题的老答案:

你的代码是正确的,而且...嗯,好吧,..。没用。因为数组可以在没有额外函数的情况下赋值给指针(请注意,您已经在函数中使用了这个函数):

代码语言:javascript
复制
int arr[5] = {1, 2, 3, 4, 5};
//int* pArr = test(arr);
int* pArr = arr;

您的函数的更多签名:

代码语言:javascript
复制
int* test (int in[5])

等同于:

代码语言:javascript
复制
int* test (int* in)

所以你看这是没有意义的。

但是这个签名需要一个数组,而不是指针:

代码语言:javascript
复制
int* test (int (&in)[5])
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12992925

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档