简体   繁体   English

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

[英]Passing an array as an argument in C++

I'm writing a merge sort function, and right now I am just using a test case array (there is no input - this is static, for now). 我正在编写一个合并排序函数,现在我只是使用一个测试用例数组(没有输入-暂时是静态的)。 I don't know how to pass an array as an argument. 我不知道如何将数组作为参数传递。 Here is my code right now: 现在是我的代码:

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

Note that this mergeSort function is not functional, as I have not figured out how to merge them yet (that's my assignment). 请注意,此mergeSort函数不起作用,因为我还没有弄清楚如何合并它们(这是我的任务)。 I would like to get my two vectors sorted before I deal with that, and I can't compile this because of my need to pass an array as an argument. 我想在处理这两个向量之前先对它们进行排序,但由于需要将数组作为参数传递,因此我无法对其进行编译。 I don't understand pointers, so if that is the solution, my excuse is ignorance. 我不理解指针,所以如果这是解决方案,我的借口就是无知。 I'm learning programming right now, with C++ as a first language, and only have a basic grasp of the language's features. 我现在正在学习编程,将C ++作为第一语言,并且对语言的功能只有基本的了解。 Thanks for the help. 谢谢您的帮助。

Jut to extend this a bit, remember that C++ arrays are exactly C arrays. 为了稍微扩展一下,请记住C ++数组恰好是 C数组。 So all you have is the address of a piece of memory that purports (with no guarantees) to be an array of somethings. 因此,您所拥有的只是一块内存的地址,该内存声称(不保证)是某物的数组。

Update 更新资料

Okay, we'll expand a little more. 好的,我们再扩展一点。

C (and therefore C++) doesn't really have "arrays" as such. C(以及C ++)实际上并没有这样的“数组”。 All it has are addresses, pointers. 它所具有的只是地址,指针。 So when you make something an "array", what really happens is you tell the compiler that some variable represents an address. 因此,当您将某个东西做成“数组”时,真正发生的是告诉编译器某个变量代表一个地址。

It's useful to make a distinction in C between a declaration and a definition . 在C中将声明定义区分开是很有用的。 In a declaration, you're simply giving something a name and a type; 在声明中,您只是在给一个名称和类型指定名称; in a definition, you actually allocate space. 在定义中,您实际上是在分配空间。

So, if we start off by definiing an array like 所以,如果我们从定义一个数组开始

int ar[100];

that means we're telling the compiler we want space for 100 int 's, we want it to all be allocated in one chunk, and we're going to use the name ar for it. 这意味着我们要告诉编译器我们需要100个int的空间,我们希望将其全部分配在一个块中,并且将使用名称ar The sizeof operator gives the number of bytes used by a type or an object, so our array ar will take up 100× sizeof(int) bytes. sizeof运算符给出了类型或对象使用的字节数,因此我们的数组ar将占用100× sizeof(int)个字节。 On most machines, that will be 400 bytes, but it varies from machine to machine. 在大多数计算机上,这将是400字节,但因计算机而异。

If we define a variable 如果我们定义一个变量

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

we're defining space for a variable that will contain an address. 我们正在为包含地址的变量定义空间。 Its size will be sizeof(int*) , which will usually be either 4 or 8, but on some machines could be anything from 2 to 16 on some machines you're unlikely to run into soon. 它的大小将为sizeof(int*) ,通常为4或8,但在某些计算机上可能是2到16之间的任何值,在某些计算机上您不太可能很快遇到。

The name of the array is ar . 数组的名称ar The compiler converts that name into an address, so we can save that address with 编译器将该名称转换为地址,因此我们可以使用

ar_p = ar ;     // THIS WORKS

Now, let's say for convenience that our array ar happened to be starting at location 1000 in memory. 现在,为了方便起见,我们的数组ar恰好是从内存中的位置1000开始的。

That name ar does not have any space allocated to it; 这名ar 没有分配给它的任何空间; it's like a constant, a number. 就像一个常数,一个数字。 So, you can't reverse that assignment 因此,您无法撤消该分配

ar = ar_p ;     // THIS WON'T WORK

for the same reason you couldn't say 出于同样的原因,你不能说

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

ie, you can't change the value of 1000. (Back in early versions of FORTRAN, this trick would work, for complicated reasons. It was a mistake. You've never lived until you've tried to debug a program in which the value of "2" is 3.) 也就是说,您不能更改1000的值。(在早期的FORTRAN版本中,由于复杂的原因,此技巧仍然有效。这是一个错误。您从未尝试过调试其中的程序, “ 2”的值为3。)

Arrays in C are always zero-based, that is, the first index is always zero. C中的数组始终基于零,也就是说,第一个索引始终为零。 Any other indices are just addresses computed using the index. 其他任何索引只是使用索引计算的地址。 So, ar[0] is just the address 1000 plus 0 bytes of offset, or 1000. ar[1] is 1000 plus 1 times the size of an int , so the next int over. 因此, ar[0]只是地址1000加0字节的偏移量,即ar[1]是1000加上int大小的1倍,因此下一个 int结束了。 And in fact, this is always true in C. 实际上,在C语言中总是如此。

This is called an array reference . 这称为数组引用

When we use the syntax *ar_p we're telling the compiler to get the thing AT the address contained in ar_p . 当我们使用*ar_p语法时,我们告诉编译器将事物AT包含在ar_p包含的地址中。 `. `。

This is called dereferencing a pointer . 这称为取消引用指针

If we say 如果我们说

ar_p = ar;

then *ar_p and ar[0] refer to the same thing. 然后*ar_par[0]指的是同一件事。

When we say ar[0] we're telling the compiler we want the thing at the address 0 bytes from ar . 当我们说ar[0]我们告诉编译器我们想要的东西是ar的地址0字节。 ar[1] is the address one int , or 4 bytes, from ar . ar[1]是地址一个int ,或4个字节,从ar So, *(ar_p+3) refers to the same thing as ar[3] . 因此, *(ar_p+3)ar[3]指的是同一事物。 (We need the parentheses because we want to add 3 to the address first and then look at the contents. *ar_p+3 would get the contents pointed to by ap_p first, and then add 3 to those. (我们需要括号,因为我们要先在地址中添加3,然后再查看内容。 *ar_p+3首先将获得ap_p指向的内容,然后再将其添加3。

The thing is, C doesn't know, or much care, how big the array really is. 问题是,C并不知道,或者非常在意数组的大小。 If I come along and do ar[365] , the compiler will happily generate code to look in the cell 1000+(365× sizeof(int) ). 如果我来做ar[365] ,编译器将愉快地生成代码以查看单元格1000+(365× sizeof(int) )。 If that's in your array, fine, but if it's just random memory, that's fine too. 如果在您的数组中,那很好,但是如果只是随机内存,那也很好。 C doesn't care. C不在乎。

(Remember C comes from the phone company. "We don't care; we don't have to. We're the Phone Company.") (记住,C来自电话公司。“我们不在乎;我们不必。我们是电话公司。”)

So, now, we know some rules, which I've moved down here. 所以,现在,我们知道了一些规则,我已经将其移至此处。 Read "≡" as "is equivalent to" or "is the same as". 读“≡”为“等同于”或“与...相同”。

What you can depend on: 您可以依靠的是:

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

Since C doesn't know a difference between pointers and arrays, you can declare either one. 由于C不知道指针与数组之间的区别,因此可以声明其中之一。 When you define a function, you can write 定义函数时,您可以编写

void foo(int[] ar){

or 要么

void foo(int* ar){

and get exactly the same effect. 并获得完全相同的效果。

  • t[i]*(t+i) t[i]*(t+i)

This was above. 以上。 Anywhere you might write ar[i] , you can replace it with *(ar+i) . 您可能会在任何地方写ar[i] ,都可以用*(ar+i)代替。 (There's actually a weird side case that breaks this, but you won't run into it as a beginner.) (实际上有一个奇怪的附带情况可以解决这个问题,但您不会以初学者的身份碰到它。)

  • where TYPE *t , (t+i) will equal the address at t plus i*sizeof(TYPE) 其中TYPE *t(t+i)等于t处的地址加上i*sizeof(TYPE)

Explained this above as well. 上面也解释了这一点。 When you index into an array, like ar[42] , it means you want the 42nd whatever over from the start address. 当您像ar[42]一样索引到数组中时,这意味着您希望从起始地址开始到第42位。 So, if you're using int , then you need to move over 42 times however wide an int is, which is to say sizeof(int) . 因此,如果您使用int ,那么您需要将int宽度移动42倍,即int宽度,即sizeof(int)

Now, that's all C, and since C++ is defined as a "kind of" C, it all holds for C++ as well. 现在,仅此而已,并且C ++被定义为C的“一种”,因此C ++也同样适用。 EXCEPT

  • unless TYPE is a user defined type that overloads operator[] and operator* . 除非TYPE是用户定义的类型,该类型会重载operator[]operator*

in C++, you can decide you want to define a new type that acts just like any other type, but you can change the way the language does specific things. 在C ++中,您可以决定要定义一个与其他任何类型一样工作的新类型,但是可以更改该语言执行特定操作的方式。 So, a programmer can decide to "overload" -- ie, replace -- the default behavior of the array reference and pointer dereference operators with something of their own devising. 因此,程序员可以决定以自己设计的方式“重载”(即替换)数组引用和指针取消引用运算符的默认行为。 As a beginner, you shouldn't be confronted with that soon, but you should be aware of it. 作为初学者,您不应该很快就遇到这种情况,但是您应该意识到这一点。

You should not use sizeof(originalarray)/sizeof(int) like that. 您不应该这样使用sizeof(originalarray)/sizeof(int) It'll only work for statically declared arrays (the size is known at compile time). 它仅适用于静态声明的数组(大小在编译时已知)。 You have to pass the size along with it. 您必须将尺寸和它一起传递。 Why don't you just make a vector out of the array and pass it instead? 您为什么不只是从数组中生成一个vector ,然后传递它呢?

Side Note: As a rule of thumb, always note that sizeof will be translated at compile time. 旁注根据经验,请始终注意sizeof将在编译时进行翻译。 So there's no way it could know the size of the array passed as an argument. 因此,不可能知道作为参数传递的数组的大小。

I see you include <vector> . 我看到您包括<vector> I suggest you do away with all uses of arrays and only use the vector class. 我建议您不要使用数组的所有用法,而只能使用vector类。 You can see examples of how to use STL containers such as vector here . 您可以在此处查看有关如何使用STL容器(例如vector示例。

  • When you pass arrays to functions, they decay to pointers to the first element of the array, the notation notwithstanding. 当您将数组传递给函数时,尽管使用了这种表示法,它们也会衰减到指向数组第一个元素的指针。 So, your sizeof doesnot work as expected. 因此,您的sizeof无法正常工作。

  • When you pass in an array, it is best to pass in the array size, so that you know where to stop. 传递数组时,最好传递数组大小,以便您知道在哪里停止。 Add it as an additional parameter. 将其添加为附加参数。

除上述所有答案外,您可能还想从c-faq.com上对阵列进行Q&A检查: http ://c-faq.com/aryptr/index.html

Unfortunately, it's very hard to do exactly what you want to do in C or C++. 不幸的是,很难完全按照C或C ++的方式进行操作。 You can pass around a fixed-size array like this: 您可以像这样传递固定大小的数组:

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

However, your array's size is not defined by a number, it's defined by the number of elements in initialization list. 但是,数组的大小不是由数字定义的,而是由初始化列表中元素的数量定义的。

The thing to do in your case (even though it's really a wrong thing to do) is to do it in two steps: 在您的情况下要做的事情(即使确实做错了事)是分两个步骤进行的:

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
}

Too bad it will not do what you need done: passing the array to a function like this makes a copy of the array, and the point of sorting would be to change the original array. 太糟糕了,它不会做您需要做的事情:将数组传递给像这样的函数会生成数组的副本,而排序的重点就是更改原始数组。

In truth, you cannot go any further without understanding the concept of "pointer". 实际上,如果不了解“指针”的概念,您将无法走得更远。

The function you need to develop really should be like this: 您实际上需要开发的功能应如下所示:

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

In other words, you pass a pointer to first element, and the number of elements. 换句话说,您将指针传递给第一个元素和元素数。

Alternatively, you can deal with vectors. 或者,您可以处理向量。 Vector encapsulates the same two things (pointer to first element and size) in a single entity called "object". 向量将两个相同的东西(指向第一个元素和大小的指针)封装在一个称为“对象”的实体中。 Plus, it manages memory for you, so you can extend the number of elements as you need. 另外,它可以为您管理内存,因此您可以根据需要扩展元素的数量。 This is the C++ way. 这是C ++的方式。 Too bad you can't initialize a vector with {...} like you can an array. 太糟糕了,您无法像使用数组一样使用{...}初始化向量。

Looks like you're using both dynamically allocated arrays and vectors, when I believe just using std::vector will be enough. 看起来您正在同时使用动态分配的数组和向量,但是我相信仅使用std :: vector就足够了。

First, let your input array be changed to a std::vector, and fill it with your input data. 首先,让您的输入数组更改为std :: vector,并用输入数据填充它。

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

Now it's important to declare your mergesort function to take a reference to a std::vector. 现在,重要的是声明您的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!
}

Just a note, looks like you're not doing an inplace sort, so expect your sort to take a while since you're copying out a lot of data. 请注意,您似乎没有进行就地排序,因此,由于要复制大量数据,因此预计您的排序会花费一些时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM