为啥必须动态分配扩展数组才能使此函数正常工作 C++

Posted

技术标签:

【中文标题】为啥必须动态分配扩展数组才能使此函数正常工作 C++【英文标题】:Why must the expanded array be dynamically allocated for this function to work properly C++为什么必须动态分配扩展数组才能使此函数正常工作 C++ 【发布时间】:2020-03-30 20:59:22 【问题描述】:

我一直在研究一个接受数组和数组大小作为参数的函数。函数的任务是创建第二个数组,其大小是第一个数组的两倍,将第一个数组的元素复制到第二个数组的前半部分,并将其余元素初始化为零。

如果我在函数中动态分配第二个数组,我只能让它工作。我怀疑这是因为一旦函数将控制权返回给调用函数,任何未动态分配的数组都会从内存中删除。换句话说,调用函数中的指针将指向垃圾数据,因为在扩展函数中创建的第二个数组现在已经消失了。谁能证实这一点?

这是用两种不同方式编写的函数。

这种方法有效

int *array_expander(int array[], int size)


    int *new_array = new int[size*2];

    for(int i0; i < size; i++)
        *(new_array + i) = *(array + i);

    for(int isize; i < size * 2; i++)
        *(new_array + i) = 0;

    return new_array;

这样不行

int *array_expander(int array[], int size)

    int new_array[size * 2];

    for(int i0; i < size; i++)
        *(new_array + i) = *(array + i);

    for(int isize; i < size * 2; i++)
        *(new_array + i) = 0;

    int *arr_ptr = new_array;

    return new_array;

【问题讨论】:

是的,你理解正确。 正确。这就是,正如我的一位老师常说的,“最糟糕的垃圾:看起来不错的垃圾。” 这能回答你的问题吗? How to return local array in C++? 更不用说,int new_array[size * 2]; 是非标准 C++,因为它是 C++ 标准不支持的 VLA(可变长度数组),但可能由编译器扩展。 正如@AlgirdasPreidžius 指出的那样,int new_array[size*2]; 不是标准 C++,因此如果您的输入已经具有可变长度,您应该移至std::vector&lt;int&gt;,因为如果size 是,则不允许使用int array[size];不是编译时常量。如果是,您可以考虑使用std::array&lt;int, N&gt;,它基本上是int[N] 的包装器,可以由函数返回。你将不得不模板化你的函数。 【参考方案1】:

一些编译器允许您这样做,但大多数编译器不允许这样做。这是因为当您使用以下方法创建数组时:

int arr[10];

这里的“10”是一个“const int”。要静态创建数组,给定的大小必须是一个常量整数。 等效地,您也可以这样做:

const int size = 10;
int arr[size];

但如果你试试这个:

int size;
cin >> size;
int arr[size]; // Illegal

您可以看到大小不是预定义的,并且会因用户输入而异。这行不通。这就是我们使用动态内存分配的原因。 我们需要这样做:

int size;
cin >> size;
int *arr = new int[size]; // You can use it like an array now!

我希望这会有所帮助! :-)

【讨论】:

感谢您的所有回复和建议。谢谢大家。 很高兴! :-) ...祝你编程好运!【参考方案2】:

你是对的。您可能不会从函数返回指向具有自动存储持续时间的本地对象的指针,因为返回的指针将无效,因为退出函数后本地对象将不活动。

此外,可变长度数组不是标准的 C++ 功能。所以这个说法

int new_array[size * 2];

不能由没有自己相应语言扩展的编译器编译。

至于函数,那么它应该被声明为

int * array_expander( const int array[], size_t size );

你应该将限定符 const 添加到第一个参数,因为传递的数组在函数中没有改变。

该功能可以使用标准算法来实现,如下面的演示程序所示。

#include <iostream>
#include <algorithm>

int * array_expander( const int array[], size_t size )

    int *new_array = new int[ 2 * size ];

    std::fill_n( std::copy( array, array + size, new_array ), size, 0 );

    return new_array;


int main() 

    int a[] =  1, 2, 3, 4, 5 ;
    const size_t N = sizeof( a ) / sizeof( *a );

    for ( const auto &item : a ) std::cout << item << ' ';
    std::cout << '\n';

    int *new_array = array_expander( a, N );
    size_t n = 2 * N;

    for ( size_t i = 0; i < n; i++ ) 
    
        std::cout << new_array[i] << ' ';
    
    std::cout << '\n';

    delete [] new_array;

    return 0;

程序输出是

1 2 3 4 5 
1 2 3 4 5 0 0 0 0 0 

请注意,您可以使用标准容器std::vector,而不是数组。

【讨论】:

"你可以使用标准容器 std::vector 代替数组" - 如果数组是固定大小的,则可以使用 std::array

以上是关于为啥必须动态分配扩展数组才能使此函数正常工作 C++的主要内容,如果未能解决你的问题,请参考以下文章

为啥指向 char 数组的指针必须需要 strcpy 才能为其数组分配字符而双引号分配不起作用?

动态内存分配

为啥在 C 中为数组声明和指向数组声明的指针动态分配的内存不同? [复制]

如何在 C 中找到动态分配数组的大小?

没有malloc的c中的动态内存分配

为啥我必须执行两次按钮功能才能使我的逻辑正常工作?