C++中数组作为函数参数或返回值

原创 2018年04月15日 16:49:15

C++中数组作为函数参数或者返回值



概述


在编程任务中,经常会遇到将数组作为函数参数或者返回值,比如在前一篇的计数排序任务中,需要额外的空间来保存排序后的元素,并且将该数组返回给主函数。本文会介绍几种可行的方案,仅供参考。

数组作为函数参数


数组作为函数函数,在Java中,通过传递数据名即可获取到数组的信息,但是在C++中,这种操作行不通,如下:

#include <iostream>
using namespace std;
int sum(int arr[]){
    int length = sizeof(arr)/sizeof(arr[0]);
    int sum = 0;
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}
int main(){
    int arr[] = {1,3,5,7,9};
    int summary = sum(arr);
    cout << summary << endl;
}

执行上述代码后发现,结果不正确,这是为什么?看下面代码:

#include <iostream>
using namespace std;
int sum(int* arr){
    int length = sizeof(arr)/sizeof(arr[0]);
    int sum = 0;
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}
int main(){
    int arr[] = {1,3,5,7,9};
    int summary = sum(arr);
    cout << summary << endl;
}

对比这两个程序,我们发现,执行结果一直,说明两个问题,首先,数组名是数组的首地址,它被传递了,其次,sum函数内部,并未获取到正确的数组长度。因此,对于数组作为函数参数的情形,我们看采用下面代码:

#include <iostream>
using namespace std;
int sum(int* arr,int length){
    int sum = 0;
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}
int main(){
    int arr[] = {1,3,5,7,9};
    int summary = sum(arr,5);
    cout << summary << endl;
}

C++11给出的替代方案,实际上该方案仍然使用模板参数传递了数组的长度,所以该参数必须要传入。并且编译器请选择:Having g++ following the coming C++0x ISO C++ language standard [-std=c++0x]

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int sum(array<int,SIZE> arr){
    int sum = 0;
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        sum += arr[i];
    }
    return sum;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};
    int summary = sum(arr);
    cout << summary << endl;
}

数组作为函数返回值


数组作为函数返回值的情况更加复杂,传统的写法容易造成产生悬挂指针,造成空间浪费。看下面代码:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int* sum(array<int,SIZE> arr){
    int length = arr.size();
    int* returnArr = new int[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    int* summary = sum(arr);
    for (int i = 0 ; i < arr.size(); i++){
        cout << summary[i] << " ";
    }
    delete[] summary;
    return 0;
}

可替代代码:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int* sum(array<int,SIZE> arr){
    int length = arr.size();
    static int returnArr[SIZE];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    int* summary = sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << summary[i] << " ";
    }
    return 0;
}

下面两段代码都是错误的,因为函数在返回后退出时,局部变量returnArr已经被删除,因此返回的结果是错误的,代码如下:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
int* sum(array<int,SIZE> arr){
    int length = arr.size();
    int returnArr[SIZE];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    int* summary = sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << summary[i] << " ";
    }
    return 0;
}
#include <iostream>
using namespace std;
int* sum(int* arr,int length){
    int returnArr[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    int arr[] = {1,3,5,7,9};
    int length = sizeof(arr)/sizeof(arr[0]);
    int* summary = sum(arr,length);
    for (int i = 0 ; i < length; i++){
        cout << summary[i] << " ";
    }
}

下面代码在int returnArr[length]前增加了static,这保证了数组在返回后没有被删除,但是此时报错:|error: storage size of ‘returnArr’ isn’t constant|

#include <iostream>
using namespace std;
int* sum(int* arr,int length){
    static int returnArr[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    int arr[] = {1,3,5,7,9};
    int length = sizeof(arr)/sizeof(arr[0]);
    int* summary = sum(arr,length);
    for (int i = 0 ; i < length; i++){
        cout << summary[i] << " ";
    }
}

下面的代码能够解决上述问题:

#include <iostream>
using namespace std;
int* sum(int* arr,int length){
    int* returnArr = new int[length];
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return returnArr;
}

int main(){
    int arr[] = {1,3,5,7,9};
    int length = sizeof(arr)/sizeof(arr[0]);
    int* summary = sum(arr,length);
    for (int i = 0 ; i < length; i++){
        cout << summary[i] << " ";
    }
    delete[] summary;
    return 0;
}

其它可行方案


在刘汝佳的《算法竞赛入门经典》教材中指出,当需要返回数组时,可以将将需要返回的数组提前作为参数传递进来,最后通过获取该数组的内容来获取其内容,这是可行的,但是该参数必要要使用引用的形式传递,否则会造成错误,代码如下:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE> arr,array<int,SIZE>& returnArr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    array<int,5> returnArr;
    sum(arr,returnArr);
    for (unsigned int i = 0 ; i < returnArr.size(); i++){
        cout << returnArr[i] << " ";
    }
    return 0;
}

错误代码如下,returnArr在传递时没有以引用形式传递:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE> arr,array<int,SIZE> returnArr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        returnArr[i] = arr[i];
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    array<int,5> returnArr;
    sum(arr,returnArr);
    for (unsigned int i = 0 ; i < returnArr.size(); i++){
        cout << returnArr[i] << " ";
    }
    return 0;
}

从上面的代码中,我们可以看到,std::array在出传递过程中,是以值方式传递,因此,想要在函数内部改变它,并且将结果返回给主调函数,必须用引用方式传值:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE> arr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        arr[i] = 0;
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    return 0;
}
//输出结果为: 1 3 5 7 9

如果改成引用传值:

#include <iostream>
#include <array>
using namespace std;

template <size_t SIZE>
void sum(array<int,SIZE>& arr){
    int length = arr.size();
    for (int i = 0 ; i < length; i++){
        arr[i] = 0;
    }
    return;
}

int main(){
    array<int,5> arr {{1,3,5,7,9}};    // C++ 11 standard
    sum(arr);
    for (unsigned int i = 0 ; i < arr.size(); i++){
        cout << arr[i] << " ";
    }
    return 0;
}
//输出结果: 0 0 0 0 0

总结


数组作为函数参数或函数返回值,如何将数组的长度返回决定了函数执行正确与否,本文给出了合适的替换方案,并且给出了示例代码,需要指出,我们应该重视C++ 11中引入的array的使用。最后,如果数组常长度不确定,建议采用vector,这在C++ 11中被认为是可变长度的数组。

  • 在std::array中,由于使用了template参数,使得在编译时获取到数组的长度,因此加static关键字即可返回正确的数组内容
  • 在传统的语法中,只能在堆区分配空间才能解决数组作为参数返回问题,但是要注意释放指针空间,否则会造成悬挂指针。
  • 如果长度不确定,可以考虑vector作为替代
  • std::array采用按值传递方式,如果想要改变其值,需要采用引用方式传值

参考资料


  1. std::array http://en.cppreference.com/w/cpp/container/array
  2. 我的github: https://github.com/JunpengCode?tab=repositories
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jpzhu16/article/details/79950684

C++数组在函数中的传递与返回

数组在函数中做形参声明时可以有两种形式①数组②指针,举例如下: void sum(int arr[],int len) {         //函数体 } void sum(int *arr...
  • songyi160
  • songyi160
  • 2016-05-14 22:06:26
  • 973

n后问题c++

#include #include #include #define N 4 //数组的下标表示皇后所在的行,数组元素的值则表示在对应行,皇后所在的列 int x[N + 1...
  • lingdi2000
  • lingdi2000
  • 2015-05-26 20:11:56
  • 473

C++ 学习之函数传参2:vector和数组传参

前面一篇博客讲到了在函数的传参中数组是不能依靠复制传递的,而vector是可以复制的,但是由于vector中通常会含有很多元素,为了避免大量的复制,可以将容器实参以引用的方式避免复制。下面主要讲讲在实...
  • guiyinzhou
  • guiyinzhou
  • 2011-04-02 13:52:00
  • 4925

详谈C++中数组作为函数参数

一、一个例子引发的思考  运行以下代码,请问输出是什么?例子来源于《剑指Offer》,我对书上例子做了修改,让其可以运行。#include using namespace std;int GetSiz...
  • oNever_say_love
  • oNever_say_love
  • 2015-10-26 12:33:48
  • 3963

C/C++学习笔记12:数组作为函数参数

在C语言的编程中经常会涉及到数组作为函数的参数,在C语言的学习中
  • gzbaishabi
  • gzbaishabi
  • 2014-07-04 16:32:21
  • 463

C++对象在作为函数参数时候的拷贝研究

介绍C++对象在作为函数参数以及返回值的copy策略一直是我困扰的一个问题,特别是在今天看到了C++11的新增加的特性std::move以及右值概念之后,激发了我的求知欲,决定把这一块详细的搞清楚。测...
  • Drecik__
  • Drecik__
  • 2018-02-06 11:38:33
  • 84

C程序设计(第四版).pdf(带书签版)

8.5.4用指向函数的指针作函数<em>参数</em>270 8.6<em>返回</em>指针值的函数274 8.7指针<em>数组</em>和...<em>C%2B%2B</em>程序设计教程.pdf 立即下载 上传者: kegende 时间: 2010-10-22 综合...
  • 2018年04月14日 00:00

C++多维数组作为函数参数该怎么写?

众所周知,函数参数中一维数组的长度会被忽略的,但二维数组的第二维度就会被要求指定长度(否则gcc会报告“数组元素的类型不完全”)。这很好理解,它是为了让函数知道矩阵的宽度。同理,三维数组就会被要求指定...
  • Frank_Jay
  • Frank_Jay
  • 2017-02-27 22:29:19
  • 2133

C++数组作为函数参数的几个问题

本文需要解决C++中关于数组的2个问题: 1. 数组作为函数参数,传值还是传址? 2. 函数参数中的数组元素个数能否确定? 先看下面的代码。   [cpp] view...
  • lz465350
  • lz465350
  • 2014-02-13 14:58:35
  • 3212

HTTP详解

1. HTTP简介          HTTP协议(HyperText Transfer Protocol,超文本传输协议)是用于从WWW服务器传输超文本到本地浏览器的传送协议。它可以使浏览器更...
  • CareChere
  • CareChere
  • 2016-06-29 11:05:45
  • 892
收藏助手
不良信息举报
您举报文章:C++中数组作为函数参数或返回值
举报原因:
原因补充:

(最多只允许输入30个字)