[英]Passing an array as an argument in C++
我正在编写一个合并排序函数,现在我只是使用一个测试用例数组(没有输入-暂时是静态的)。 我不知道如何将数组作为参数传递。 现在是我的代码:
//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 ++数组恰好是 C数组。 因此,您所拥有的只是一块内存的地址,该内存声称(不保证)是某物的数组。
好的,我们再扩展一点。
C(以及C ++)实际上并没有这样的“数组”。 它所具有的只是地址,指针。 因此,当您将某个东西做成“数组”时,真正发生的是告诉编译器某个变量代表一个地址。
在C中将声明和定义区分开是很有用的。 在声明中,您只是在给一个名称和类型指定名称; 在定义中,您实际上是在分配空间。
所以,如果我们从定义一个数组开始
int ar[100];
这意味着我们要告诉编译器我们需要100个int
的空间,我们希望将其全部分配在一个块中,并且将使用名称ar
。 sizeof
运算符给出了类型或对象使用的字节数,因此我们的数组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
没有分配给它的任何空间; 就像一个常数,一个数字。 因此,您无法撤消该分配
ar = ar_p ; // THIS WON'T WORK
出于同样的原因,你不能说
1000 = ar_p ; // THIS WON'T WORK EITHER
也就是说,您不能更改1000的值。(在早期的FORTRAN版本中,由于复杂的原因,此技巧仍然有效。这是一个错误。您从未尝试过调试其中的程序, “ 2”的值为3。)
C中的数组始终基于零,也就是说,第一个索引始终为零。 其他任何索引只是使用索引计算的地址。 因此, ar[0]
只是地址1000加0字节的偏移量,即ar[1]
是1000加上int
大小的1倍,因此下一个 int结束了。 实际上,在C语言中总是如此。
这称为数组引用 。
当我们使用*ar_p
语法时,我们告诉编译器将事物AT包含在ar_p
包含的地址中。 `。
这称为取消引用指针 。
如果我们说
ar_p = ar;
然后*ar_p
和ar[0]
指的是同一件事。
当我们说ar[0]
我们告诉编译器我们想要的东西是ar
的地址0字节。 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 foo(TYPE * t)
由于C不知道指针与数组之间的区别,因此可以声明其中之一。 定义函数时,您可以编写
void foo(int[] ar){
要么
void foo(int* ar){
并获得完全相同的效果。
t[i]
≡ *(t+i)
以上。 您可能会在任何地方写ar[i]
,都可以用*(ar+i)
代替。 (实际上有一个奇怪的附带情况可以解决这个问题,但您不会以初学者的身份碰到它。)
TYPE *t
, (t+i)
等于t
处的地址加上i*sizeof(TYPE)
上面也解释了这一点。 当您像ar[42]
一样索引到数组中时,这意味着您希望从起始地址开始到第42位。 因此,如果您使用int
,那么您需要将int
宽度移动42倍,即int
宽度,即sizeof(int)
。
现在,仅此而已,并且C ++被定义为C的“一种”,因此C ++也同样适用。 除
TYPE
是用户定义的类型,该类型会重载operator[]
和operator*
。 在C ++中,您可以决定要定义一个与其他任何类型一样工作的新类型,但是可以更改该语言执行特定操作的方式。 因此,程序员可以决定以自己设计的方式“重载”(即替换)数组引用和指针取消引用运算符的默认行为。 作为初学者,您不应该很快就遇到这种情况,但是您应该意识到这一点。
您不应该这样使用sizeof(originalarray)/sizeof(int)
。 它仅适用于静态声明的数组(大小在编译时已知)。 您必须将尺寸和它一起传递。 您为什么不只是从数组中生成一个vector
,然后传递它呢?
旁注:根据经验,请始终注意sizeof
将在编译时进行翻译。 因此,不可能知道作为参数传递的数组的大小。
我看到您包括<vector>
。 我建议您不要使用数组的所有用法,而只能使用vector
类。 您可以在此处查看有关如何使用STL容器(例如vector
示例。
当您将数组传递给函数时,尽管使用了这种表示法,它们也会衰减到指向数组第一个元素的指针。 因此,您的sizeof
无法正常工作。
传递数组时,最好传递数组大小,以便您知道在哪里停止。 将其添加为附加参数。
除上述所有答案外,您可能还想从c-faq.com上对阵列进行Q&A检查: 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!
}
请注意,您似乎没有进行就地排序,因此,由于要复制大量数据,因此预计您的排序会花费一些时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.