如何在C++函数中返回数组?

4

我是一个C++新手,我想知道如何从C++函数中返回一个数组。
我尝试了下面的代码,但似乎不起作用。

```cpp int[] myFunction() { int myArray[3] = {1, 2, 3}; return myArray; } ```

要在C++中返回数组,您需要使用指针。以下是一个示例代码:

```cpp int* myFunction() { static int myArray[3] = {1, 2, 3}; return myArray; } ```

请注意,必须使用静态数组并将其声明为指针才能从函数中返回。此外,如果您在函数内部创建数组,则该数组将在函数结束时被销毁,因此无法返回。

char some_function(){
    char my_string[] = "The quick brown fox jumps over the lazy dog";
    return my_string;
}

该函数的返回类型是一个单个字符,而不是字符数组。然而,指定一个数组返回类型并不能帮助太多——请参考wheaties的回答。 - user180247
6个回答

5

代码无法正常运行的原因是函数结束时,你创建的字符串的生命周期也随之结束。相反地,如果你要在C++中工作,请使用std::string并返回它。

std::string myFunc(){
    return string("hey a new string");
}

对于其他数组,请使用std::vectorstd::deque或其他STL类之一。我还要指出的是,您需要查看STL(标准模板库):

vector<float> myFunc(){
    vector<float> blah;
    blah.push_back(4.5);
    blah.push_back(5.7);
    return blah;
 }

关于返回数组:

指针等问题的一个大问题是对象生命周期的考虑。例如以下代码:

int* myFunc(){
    int myInt = 4;
    return &myInt;
}

这里发生的事情是当函数退出时,myInt 不再存在,指针返回到某个内存地址,可能包含值为4的内容,也可能不包含。如果想要使用指针返回数组(我建议您不要这样做,而是使用 std::vector),代码应该类似于:

int* myFunc(){
    return new int[4];
}

它使用new操作符。


哪个头文件应该包含? 能否在不使用STL的情况下返回整数数组? - SteepCurver
@ScienceCrazy 对于 std::string,需要包含头文件 #include <string> ,并在文件顶部写上 using std::string。另外,我已经修改了我的答案。我真诚地鼓励您不要在函数返回时使用裸指针,因为调用者不知道他们是否需要清理指向的内存。 - wheaties
你应该坚持在所有地方使用 std:: 或者完全不使用它。 - zneak
甚至更好的是 ::std-。请参见https://dev59.com/JXI-5IYBdhLWcg3w0MDx。 - Omnifarious
1
@ScienceCrazy - 如果你真的想返回一个整数数组,你需要确保你返回的是一个(复制的)数组,而不仅仅是一个(悬浮的)指针。如果你定义了一个具有数组成员的结构体/类,这是可能的,但这很麻烦。从C语言时代开始的常规技巧是不使用返回值,而是传递一个参数,该参数引用了您将存储输出的位置。在C++中,使用引用类型可以更好地解决这个问题。但通常情况下,你应该使用标准库容器而不是数组。它们更加灵活和健壮。 - user180247

2

在几乎所有情况下,在C++中使用std::string比使用char数组更好。

更一般地说,考虑使用STL容器类而不是C风格的数组。

以下是一些例子...

#include <string>
#include <vector>

std::string some_function()
{
    return "The quick brown fox jumps over the lazy dog";
}

std::vector<std::string> some_other_function()
{
    std::vector<std::string> stuff;
    stuff.push_back("Spam");
    stuff.push_back("Spam");
    stuff.push_back("Spam");
    stuff.push_back("Spam");
    stuff.push_back("Spam");
    stuff.push_back("Spam");
    stuff.push_back("Spam");
    return stuff;
}

1

如果你可以使用标准容器,那么你应该使用它。在你的具体例子中,你应该使用的容器是std::string,因为:

#include <string>
std::string some_function(){
    std::string my_string = "The quick brown fox jumps over the lazy dog";
    return my_string;
}

如果您确实需要传递一个实际的数组,那么您必须要做更多的事情。最好的选择可能是让调用者解决数组的细节,并将其作为参数传递给被调用者:代码如下:
// notice here that we use 'string.h', with the '.h' extension, different from above
#include <string.h>


void some_function(size_t len, char * dest)
{
    std::strncpy(dest, "The quick brown fox jumps over the lazy dog", len);
}

int main()
{
    const std::size_t stringSize = 100;
    char myString[stringSize];
    some_function(stringSize, myString);
}

另一个选择,虽然在许多情况下甚至更不理想,是分配一个新的存储区域来容纳数组。

char* some_function()
{
    char* result = new char[44];
    strcpy(result, "The quick brown fox jumps over the lazy dog");
    return result;
}


int main()
{
    char *myString = some_function();
    // do some stuff with myString
    delete myString[];
}

第一个例子需要注意...如果源字符串的长度大于等于len,strncpy()将不会包含空终止符。为了安全起见,在调用strncpy()之后,您可以显式地添加一个空终止符(例如,dest[len - 1] = '\0';)。 - cbranch

0

这将会因为内存模型而崩溃。

在C++(以及许多其他语言)中,有两个流行的内存分配位置:栈和堆。

在C++中,栈是函数执行期间放置所需值的特殊内存区域。最重要的是要记住,无论放置什么都会在函数返回时被删除。这意味着如果您返回指向栈上某个内容的指针,则程序必定会崩溃,因为那里曾经存在的任何内容都不再存在了。如果返回一个数组,就会出现这种情况。

希望有一个地方可以永久存储数据(“永久”是指整个程序运行期间):堆。如果在堆上分配了某些内容,则在函数返回时它不会被清除。但是,这意味着需要额外的记录,因为您很容易失去对某个已分配内存块的所有引用。如果发生这种情况,则无法回收它(这称为泄漏,这是一件非常糟糕的事情)。因此,建议遵循一个规则:如果函数在堆上分配内存,则应负责释放它。问题是,如果您的函数返回已分配的内存,则显然无法处理它。因此,您不应在堆上分配内存并将其返回。

那么,如果你不能在栈上分配数组,也不能返回堆上的内存指针,那么你该怎么办呢?

我建议您使用C++类型来解决您的问题。如果您要使用字符数组,最好使用std::string#include <string>)。如果您要使用其他任何类型的数组,则最好使用std::vector<YourTypeHere>#include <vector>)。两者都管理自己的内存,因此安全地返回它们。

这里和Google上都有充足的文档。这里是一个快速示例。

std::vector<int> foo()
{
    std::vector<int> my_vector;
    my_vector.push_back(1);
    my_vector.push_back(2);
    my_vector.push_back(3);
    return my_vector;
}

std::string bar()
{
    std::string my_string = "The quick brown fox jumps over the lazy dog";
    return my_string;
}

int main()
{
    std::vector<int> my_vector = foo();
    // will print 123
    std::cout << my_vector[0] << my_vector[1] << my_vector[2] << std::endl;

    std::string my_string = bar();
    // will print The quick brown fox jumps over the lazy dog
    std::cout << my_string << std::endl;
}

但对于字符串字面量来说,情况并非如此:https://dev59.com/0HE95IYBdhLWcg3wY9D6 - Andreas Brinck
@Andreas Brinck 字符串字面量存储在可执行文件的数据段中,因此您可以随时返回指向它们的指针。 - zneak
@Andreas Brinck 很好!我们达成了一致。 - zneak

0

这是因为你试图从函数调用中返回的变量是一个临时变量,它在堆栈中创建,并且堆栈变量一旦控制流程退出块就会被清除。因此,你返回的指针指向的是已经被删除的变量。

如果你想从函数中返回某些内容,其中一种替代方法是传递一个地址给该函数,并将变量放入该地址。

void some_function(string& some_string){
    char my_string[] = "The quick brown fox jumps over the lazy dog";
    some_string = my_string;
}

0

有两种方法可以在没有STL的情况下完成这个任务。一种是使用“out”参数,另一种是滥用结构体。以下是第一种方法的实现:

#include <cstddef>  // For ::std::size_t
#include <cstring>  // For strncpy
void some_function(char retval[], ::std::size_t retval_len) {
    char my_string[] = "The quick brown fox jumps over the lazy dog";
    ::std::strncpy(retval, my_string, retval_len);
}

以下是第二种方法的工作原理:

struct array_struct {
    char the_array[50];
};

array_struct some_function() {
    array_struct ary = { "The quick brown fox jumps over the lazy dog" };
    return ary;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接