将数组作为参数传递给C ++

问题描述 投票:13回答:7

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

//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);
}

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

c++ arrays sorting mergesort divide-and-conquer
7个回答
31
投票

要稍微扩展一下,请记住C ++数组是exactly C数组。因此,您所拥有的只是一块内存的地址,该内存声称(不保证)是某物的数组。

更新

好的,我们再扩展一点。

C(因此是C ++)实际上没有这样的“数组”。它所具有的只是地址,指针。因此,当您将某个东西做成“数组”时,真正发生的是告诉编译器某个变量代表一个地址。

在C中区分declarationdefinition是很有用的。在声明中,您只是在给一个名称和类型指定名称;在定义中,您实际上是在分配空间。

所以,如果我们先定义一个数组,如

int ar[100];

这意味着我们要告诉编译器我们要100个int的空间,我们希望将其全部分配到一个块中,并且我们将使用名称arsizeof运算符提供了类型或对象使用的字节数,因此我们的数组ar将占用100×sizeof(int)个字节。在大多数计算机上,这将是400个字节,但因计算机而异。

如果我们定义一个变量

int * ar_p;   // using '_p' as a reminder this is a pointer

我们正在为将包含地址的变量定义空间。它的大小将为sizeof(int*),通常为4或8,但在某些计算机上可能会是2到16之间的任何值,在某些不太可能很快会出现的计算机上。

数组的名称ar。编译器将该名称转换为地址,因此我们可以使用[

保存该地址
ar_p = ar ;     // THIS WORKS

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

该名称ar确实not没有为其分配任何空间;就像一个常数,一个数字。因此,您无法撤消该任务

ar = ar_p ;     // THIS WON'T WORK

出于同样的原因,您不能说

1000 = ar_p ;   // THIS WON'T WORK EITHER

即,您不能更改1000的值。(在早期版本的FORTRAN中,由于复杂的原因,此技巧仍然有效。这是一个错误。在尝试调试程序之前,您从未活过。其中“ 2”的值为3。)

C中的数组始终基于零,也就是说,第一个索引始终为零。其他任何索引只是使用索引计算的地址。因此,ar[0]只是地址1000加0字节的偏移量,即1000。ar[1]是1000加上int大小的1倍,因此next int结束。实际上,在C语言中总是如此。

这称为数组引用

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

这称为取消引用指针

如果我们说

ar_p = ar;

然后*ar_par[0]指的是同一件事。

[当我们说ar[0]时,我们告诉编译器我们想要的东西在ar中的0字节地址处。 ar[1]是从int开始的一个地址ar或4个字节。因此,*(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){

void foo(int* ar){

并获得完全相同的效果。

  • t[i]*(t+i)

    以上。可以在任何位置编写ar[i]的地方,都可以用*(ar+i)代替。 (实际上有一个奇怪的附带情况可以解决这个问题,但您不会像初学者那样碰到它。)

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

    也在上面解释了这一点。当您像ar[42]这样索引到数组时,这意味着您希望从起始地址开始到第42位。因此,如果您使用的是int,那么您需要将int的宽度移动42倍,也就是说sizeof(int)

    现在,这就是所有C,并且由于C ++被定义为C的“一种”,所以C ++也都适用。除外

  • 除非TYPE是用户定义的类型,该类型会使operator[]operator*超载。

    在C ++中,您可以决定要定义一个与其他任何类型一样工作的新类型,但是您可以更改该语言执行特定操作的方式。因此,程序员can

  • 决定以自己设计的方式“重载”(即替换)数组引用和指针取消引用运算符的默认行为。作为初学者,您不应该很快就遇到这种情况,但是您应该意识到这一点。

您不应该这样使用sizeof(originalarray)/sizeof(int)。它仅适用于静态声明的数组(大小在编译时已知)。您必须将尺寸和它一起传递。您为什么不只从数组中制作一个vector并传递它呢?

附带说明:

根据经验,请始终注意,sizeof将在编译时进行翻译。因此,不可能知道作为参数传递的数组的大小。

我看到你加入了<vector>。我建议您不要使用所有数组,而只使用vector类。您可以看到有关如何使用STL容器的示例,例如vector here

  • 尽管将符号传递给函数时,它们会衰减为指向数组第一个元素的指针。因此,您的sizeof无法正常工作。

  • 当您传递数组时,最好传递数组大小,以便您知道在哪里停止。将其添加为附加参数。

  • 除了以上所有答案之外,您可能还想从c-faq.com上检查阵列上的问题和答案:http://c-faq.com/aryptr/index.html

    不幸的是,要完全按照C或C ++的方式进行操作非常困难。您可以像这样传递固定大小的数组:

    int mergeSort(int originalarray[20])
    {
        // do something
    }
    

    但是,数组的大小不是由数字定义的,而是由初始化列表中元素的数量定义的。

    在您的情况下要做的事情(尽管这确实是错误的事情)是分两个步骤进行:

    int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
    const size_t arraySize = sizeof originalarray / sizeof originalarray[0];
    int mergeSort(int array[arraySize])
    {
        // do something
    }
    

    太糟糕了,它不会做您需要做的事情:将数组传递给这样的函数会复制数组,而排序的重点就是更改原始数组。

    实际上,如果不了解“指针”的概念,您将无法再进一步。

    您真正需要开发的功能应该是这样的:

    int originalarray[] = {1, 3, 5, 7, 9, 2, 4, 6, 8, 10};
    const size_t arraySize = sizeof originalarray / sizeof originalarray[0];
    
    int mergeSort(int *array, const size_t size)
    {
        // do something
    }
    
    mergeSort(&(originalArray[0]), arraySize);
    

    换句话说,将指针传递给第一个元素和元素数。

    或者,您可以处理向量。向量将两个相同的东西(指向第一个元素和大小的指针)封装在一个称为“对象”的实体中。另外,它可以为您管理内存,因此您可以根据需要扩展元素的数量。这是C ++的方式。太糟糕了,您无法像数组一样使用{...}初始化向量。

    当您相信仅使用std :: vector就足够了时,您似乎同时使用了动态分配的数组和向量。

    首先,将输入数组更改为std :: vector,并用输入数据填充它。

    int main()
    {
       std::vector<int> originalarray;
       for (int data = 1; data <= 10; data++)
       {
          originalarray.push_back(data);
       }
       mergeSort(originaldata);
    }
    

    现在,重要的是声明您的mergesort函数以引用对std :: vector的引用。

    int mergeSort(std::vector<int>& originalarray)
    {
       // The rest of your code, note that now you are passing 
       // in your array for sorting, so you can continue with your code to split
       // the vector into farray and sarray
    
       // then call sort on your halves.
       mergeSort(farray);
       mergeSort(sarray);
    
       // I'm guessing at this point you'd write code to combine your farray sarray, and
       // put it back into originalarray...don't forget to clear original array first!
    }
    

    只是一个注释,看起来您不是在进行就地排序,因此,由于要复制大量数据,因此希望您的排序需要一段时间。


    18
    投票

    您不应该这样使用sizeof(originalarray)/sizeof(int)。它仅适用于静态声明的数组(大小在编译时已知)。您必须将尺寸和它一起传递。您为什么不只从数组中制作一个vector并传递它呢?


    3
    投票

    我看到你加入了<vector>。我建议您不要使用所有数组,而只使用vector类。您可以看到有关如何使用STL容器的示例,例如vector here


    2
    投票
    • 尽管将符号传递给函数时,它们会衰减为指向数组第一个元素的指针。因此,您的sizeof无法正常工作。


    0
    投票

    除了以上所有答案之外,您可能还想从c-faq.com上检查阵列上的问题和答案:http://c-faq.com/aryptr/index.html


    0
    投票

    不幸的是,要完全按照C或C ++的方式进行操作非常困难。您可以像这样传递固定大小的数组:


    0
    投票

    当您相信仅使用std :: vector就足够了时,您似乎同时使用了动态分配的数组和向量。

    © www.soinside.com 2019 - 2024. All rights reserved.