在C++中将数组作为参数传递

jke*_*eys 13 c++ arrays sorting mergesort divide-and-conquer

我正在编写一个合并排序函数,现在我只使用一个测试用例数组(没有输入 - 这是静态的,现在).我不知道如何将数组作为参数传递.这是我现在的代码:

//merge sort first attempt

#include <iostream>

#include <algorithm>

#include <vector>

int mergeSort(int[]);
int main() {
    int originalarray[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 10 };
    mergeSort(originalarray[]);
}

int mergeSort(int[] originalarray) {
    int num = (sizeof(originalarray) / sizeof(int));
    std::vector < int > original(num);

    if (num > 2) {
        return num;
    }

    // Fill the array using the elements of originalarray
    // This is just for demonstration, normally original will be a parameter,
    // so you won't be filling it up with anything.
    std::copy(originalarray, originalarray + num, original.begin());

    // Create farray and sarray of the appropriate size
    std::vector < int > farray(num / 2);
    std::vector < int > sarray(num - farray.size());

    // Fill those using elements from original
    std::copy(original.begin(), original.begin() + farray.size(), farray.begin());
    std::copy(original.begin() + farray.size(), original.end(), sarray.begin());

    mergeSort(farray);
    mergeSort(sarray);
}
Run Code Online (Sandbox Code Playgroud)

}

请注意,这个mergeSort函数不起作用,因为我还没有弄清楚如何合并它们(这是我的任务).我想在处理之前对我的两个向量进行排序,因为我需要将数组作为参数传递,所以无法编译.我不明白指针,所以如果这是解决方案,我的借口就是无知.我正在学习编程,使用C++作为第一语言,并且只能基本掌握语言的功能.谢谢您的帮助.

Cha*_*tin 31

请稍微扩展一下,请记住C++数组正是 C数组.所以你所拥有的只是一块内存的地址,它声称(不保证)是一些东西.

更新

好的,我们会再扩展一点.

C(因此C++)实际上没有"数组".它只有地址,指针.因此,当你创建一个"数组"时,真正发生的是你告诉编译器某个变量代表一个地址.

声明定义之间区分C是有用的.在一个声明中,你只是给出一个名字和类型的东西; 在定义中,您实际上是分配空间.

所以,如果我们从定义数组开始

int ar[100];
Run Code Online (Sandbox Code Playgroud)

这意味着我们告诉编译器我们想要100 int的空间,我们希望它全部分配在一个块中,我们将使用ar它的名称.所述sizeof操作者给出通过类型或对象所使用的字节数,所以我们的阵列ar将占用100× sizeof(int)字节.在大多数机器上,这将是400字节,但它随机器而异.

如果我们定义一个变量

int * ar_p;   // using '_p' as a reminder this is a pointer
Run Code Online (Sandbox Code Playgroud)

我们为包含地址的变量定义空间.它的大小sizeof(int*)通常是4或8,但在某些机器上可能是2到16之间的任何东西,你不太可能很快遇到.

数组的名称ar.编译器将该名称转换为地址,因此我们可以保存该地址

ar_p = ar ;     // THIS WORKS
Run Code Online (Sandbox Code Playgroud)

现在,为方便起见,我们的数组ar恰好是从内存中的1000位开始.

这个名字ar不会为它分配任何空间; 它就像一个常数,一个数字.所以,你无法扭转这一任务

ar = ar_p ;     // THIS WON'T WORK
Run Code Online (Sandbox Code Playgroud)

出于同样的原因你不能说

1000 = ar_p ;   // THIS WON'T WORK EITHER
Run Code Online (Sandbox Code Playgroud)

也就是说,你不能改变1000的值.(回到FORTRAN的早期版本,这个技巧会起作用,原因很复杂.这是一个错误.在你试图调试一个程序之前你从未活过"2"的值是3.)

C中的数组总是从零开始,也就是说,第一个索引始终为零.任何其他索引只是使用索引计算的地址.所以,ar[0]只是地址1000加0字节的偏移量,或1000. ar[1]是1000加1的大小的一个int,所以下一个 int结束.事实上,这在C中总是如此.

这称为数组引用.

当我们使用语法时,*ar_p我们告诉编译器将事物AT包含在其中的地址中ar_p.`.

这称为解除引用指针.

如果我们说

ar_p = ar;
Run Code Online (Sandbox Code Playgroud)

然后*ar_par[0]指同样的事情.

当我们说ar[0]我们告诉编译器时,我们希望地址为0字节ar. ar[1]来自的地址是一个int或4个字节ar.所以,*(ar_p+3)指的是同样的事情ar[3].(我们需要括号,因为我们想首先在地址中添加3,然后查看内容. *ar_p+3首先获取指向的内容ap_p,然后再添加3.

问题是,C不知道,或者非常关心,阵列究竟有多大.如果我一起来做ar[365],编译器将很乐意生成代码以查看单元格1000+(365× sizeof(int)).如果那是在你的阵列中,那很好,但如果它只是随机记忆,那也没关系.C不关心.

(记得C来自电话公司."我们不在乎;我们没有.我们是电话公司.")

所以,现在,我们知道一些规则,我已经在这里移动了.将"≡"读作"相当于"或"与...相同".

你可以依靠什么:

  • foo(TYPE t[])foo(TYPE * t)

由于C不知道指针和数组之间的区别,因此可以声明其中一个.定义函数时,可以编写

void foo(int[] ar){
Run Code Online (Sandbox Code Playgroud)

要么

void foo(int* ar){
Run Code Online (Sandbox Code Playgroud)

并获得完全相同的效果.

  • t[i]*(t+i)

这是上面的.您可以写的任何地方ar[i],您都可以替换它*(ar+i).(实际上有一个奇怪的侧面案例打破了这一点,但你不会作为一个初学者遇到它.)

  • 其中TYPE *t,(t+i)将等于t加号的地址i*sizeof(TYPE)

上面也解释了这一点.当你索引到一个数组时ar[42],就意味着你想要从开始地址开始的42次.所以,如果你正在使用int,那么你需要移动超过42倍int,也就是说sizeof(int).

现在,这就是所有C,并且由于C++被定义为"一种"C,它也适用于C++.除了

  • 除非TYPE用户定义的类型重载operator[]operator*.

在C++中,您可以决定要定义一个与任何其他类型一样的新类型,但您可以更改语言执行特定操作的方式.因此,程序员可以决定"重载" - 即替换 - 数组引用和指针解引用运算符的默认行为与他们自己设计的东西.作为一个初学者,你不应该很快面对,但你应该意识到这一点.

  • 啊.好的,我会补充一些. (3认同)
  • 感谢Alex的客气话,但实际上理解这一点也会对您对Java / C#的理解产生很大的不同。例如,当您说Object a = new Object();时您会得到什么?在Java中。真正的“ a”是什么? (2认同)

Meh*_*ari 19

你不应该这样使用sizeof(originalarray)/sizeof(int).它只适用于静态声明的数组(大小在编译时是已知的).你必须传递它的大小.你为什么不vector从数组中取出并传递它?

附注:根据经验,请注意sizeof将在编译时进行翻译.因此,它无法知道作为参数传递的数组的大小.