本文介绍了为什么 C++ 不支持函数返回数组?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

某些语言使您可以像 Java 等普通函数一样声明一个返回数组的函数:

Some languages enable you to just declare a function returning an array like a normal function, like Java:

public String[] funcarray() {
   String[] test = new String[]{"hi", "hello"};
   return test;
}

为什么 C++ 不支持 int[] funcarray(){} 之类的东西?您可以返回一个数组,但是制作这样一个函数真的很麻烦.而且,我在某处听说字符串只是字符数组.所以如果你能在 C++ 中返回一个字符串,为什么不能返回一个数组?

Why doesn't C++ support something like int[] funcarray(){} ?You can return an array, but it's a real hassle to make such a function. And also, I heard somewhere that strings are just arrays of char. So if you can return a string in C++, why not an array?

推荐答案

我敢打赌,为了简洁,这只是一个设计决定.更具体地说,如果你真的想知道为什么,你需要从头开始.

I'd wager a guess that to be concise, it was simply a design decision. More specifically, if you really want to know why, you need to work from the ground up.

让我们首先考虑 C.在 C 语言中,按引用传递"和按值传递"有明显的区别.轻描淡写地说,C 中的数组名实际上只是一个指针.出于所有意图和目的,差异(通常)归结为分配.代码

Let's think about C first. In the C language, there is a clear distinction between "pass by reference" and "pass by value". To treat it lightly, the name of an array in C is really just a pointer. For all intents and purposes, the difference (generally) comes down to allocation. The code

int array[n];

将在堆栈上创建 4*n 字节的内存(在 32 位系统上),与进行声明的任何代码块的范围相关.反过来,

would create 4*n bytes of memory (on a 32 bit system) on the stack correlating to the scope of whichever code block makes the declaration. In turn,

int* array = (int*) malloc(sizeof(int)*n);

将创建相同数量的内存,但在堆上.在这种情况下,该内存中的内容与范围无关,只有对内存的引用受范围限制.这就是按值传递和按引用传递的用武之地.正如您可能知道的那样,按值传递意味着当某些东西被传入或从函数返回时,被传递的东西"是对变量求值的结果.换句话说,

would create the same amount memory, but on the heap. In this case, what is in that memory isn't tied to the scope, only the reference TO the memory is limited by the scope. Here's where pass by value and pass by reference come in. Passing by value, as you probably know, means that when something is passed in to or returned from a function, the "thing" that gets passed is the result of evaluating the variable. In other words,

int n = 4;
printf("%d", n);

将打印数字 4,因为结构 n 的计算结果为 4(对不起,如果这是基本的,我只想涵盖所有基础).这个 4 与你的程序的内存空间完全没有关系或关系,它只是一个文字,所以一旦你离开了那个 4 有上下文的范围,你就失去了它.通过引用传递呢?在函数的上下文中按引用传递没有什么不同;您只需评估通过的构造.唯一的区别是在评估传递的事物"之后,您将评估结果用作内存地址.我曾经有一个特别愤世嫉俗的 CS 讲师,他喜欢说没有通过引用传递这样的东西,只是传递聪明值的一种方式.真的,他是对的.所以现在我们从函数的角度考虑作用域.假设你可以有一个数组返回类型:

will print the number 4 because the construct n evaluates to 4 (sorry if this is elementary, I just want to cover all the bases). This 4 has absolutely no bearing or relationship to the memory space of your program, it's just a literal, and so once you leave the scope in which that 4 has context, you lose it. What about pass by reference? Passing by reference is no different in the context of a function; you simply evaluate the construct that gets passed. The only difference is that after evaluating the passed "thing", you use the result of the evaluation as a memory address. I once had a particular cynical CS instructor who loved to state that there is no such thing as passing by reference, just a way to pass clever values. Really, he's right. So now we think about scope in terms of a function. Pretend that you can have an array return type:

int[] foo(args){
    result[n];
    // Some code
    return result;
}

这里的问题是结果计算为数组第 0 个元素的地址.但是,当您尝试从该函数的外部(通过返回值)访问该内存时,就会遇到问题,因为您尝试访问的内存不在您正在使用的范围内(函数调用的堆栈).所以我们解决这个问题的方法是使用标准的通过引用传递"jiggery-pokery:

The problem here is that result evaluates to the address of the 0th element of the array. But when you attempt to access this memory from outside of this function (via the return value), you have a problem because you are attempting to access memory that is not in the scope with which you are working (the function call's stack). So the way we get around this is with the standard "pass by reference" jiggery-pokery:

int* foo(args){
    int* result = (int*) malloc(sizeof(int)*n));
    // Some code
    return result;
}

我们仍然得到一个指向数组第 0 个元素的内存地址,但现在我们可以访问该内存.

We still get a memory address pointing to the 0th element of the Array, but now we have access to that memory.

我的意思是什么?在 Java 中,通常会断言一切都是按值传递".这是真的.上面那个愤世嫉俗的讲师也对 Java 和 OOP 大体上说过:一切都只是一个指针.他也是对的.尽管 Java 中的所有内容实际上都是按值传递的,但几乎所有这些值实际上都是内存地址.因此,在 Java 中,该语言确实允许您返回数组或字符串,但它是通过将其转换为带有指针的版本来实现的.它还为您管理您的记忆.自动内存管理虽然有用,但效率不高.

What's my point? In Java, it is common to assert that "everything is pass by value". This is true. The same cynical instructor from above also had this to say about Java and OOP in general: Everything is just a pointer. And he's also right. While everything in Java is in fact pass by value, almost all of those values are actually memory addresses. So in Java, the language does let you return an array or a String, but it does so by turning it in to the version with pointers for you. It also manages your memory for you. And automatic memory management, while helpful, is not efficient.

这将我们带到了 C++.C++ 被发明的全部原因是因为 Bjarne Stroustrup 在他的博士研究期间一直在试验 Simula(基本上是原始的 OOPL),并认为它在概念上非常棒,但他注意到它的表现相当糟糕.于是他开始研究所谓的 C with Classes,它被重命名为 C++.在这样做的过程中,他的目标是制作一种编程语言,该语言吸收了 Simula 的一些最佳功能,但仍保持强大和快速.他选择扩展 C 是因为它已经具有传奇般的性能,一个权衡是他选择不像其他 OOPL 那样大规模地实现自动内存管理或垃圾收集.从模板类之一返回数组是有效的,因为您正在使用一个类.但是如果你想返回一个 C 数组,你必须用 C 的方式来做.换句话说,C++ 确实支持以与 Java 完全相同的方式返回数组;它只是不会为您完成所有工作.因为一个丹麦人认为它太慢了.

This brings us to C++. The whole reason C++ was invented was because Bjarne Stroustrup had been experimenting with Simula (basically the original OOPL) during his PhD work, and thought it was fantastic conceptually, but he noticed that it performed rather terribly. And so he began working on what was called C with Classes, which got renamed to C++. In doing so, his goal was to make a programming language that took SOME of the best features from Simula but remained powerful and fast. He chose to extend C due to its already legendary performance, and one tradeoff was that he chose to not implement automatic memory management or garbage collecting on such a large scale like other OOPL's. Returning an array from one of the template classes works because, well, you're using a class. But if you want to return a C array, you have to do it the C way. In other words, C++ does support returning an array EXACTLY the same way that Java does; it just doesn't do all of the work for you. Because a Danish dude thought it'd be too slow.

这篇关于为什么 C++ 不支持函数返回数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-24 03:13