简体   繁体   English

将数组从函数返回到main

[英]Returning array from a function back to main

I have a local character array in a function that is manipulated according to the logic in the function. 我在函数中有一个本地字符数组,该数组根据函数中的逻辑进行操作。 The function return the pointer to the array as follows 该函数将指针返回数组,如下所示

char * fn(void)
{
   char str[20] = "Hello";
   cout << str; // This prints the string Hello perfectly
   // Some operations on string
   return str;
}

int main()
{
   char *ptr;
   ptr=fn();
   cout << ptr; // This prints only the first character of the string i.e H
}

How can I pass an array from a function back to main. 如何将数组从函数传递回main。

I know I should not pass address of a local variable back to main as that stack of the program is modified. 我知道我不应该在修改程序堆栈时将局部变量的地址传递回main。 But still if I use cout << *ptr then the output is just the first character "H". 但是,如果我使用cout << * * ptr,那么输出只是第一个字符“ H”。 I solved the problem by using a dynamically allocated memory for the array using "new". 我通过使用“ new”为数组使用动态分配的内存解决了该问题。 But I would like to know the reason behind this behavious (Does this have to do something with Stack ?? ) 但是我想知道这个行为背后的原因(这是否与Stack ??有关?)

if you create the array in the function how you did it, it is in deed created on the stack, and will be destroyed, when you leave the function. 如果您在函数中创建数组的方式是一样的,则它实际上是在堆栈上创建的,并且在离开函数时将被销毁。 A usual way to manipulate arrays through functions would be, to pass the pointer to an already existing array as a function parameter. 通过函数操作数组的通常方法是将指针作为函数参数传递给已存在的数组。 When you modify it in the function then, it will also be modified outside of the function. 当您在函数中对其进行修改时,也会在函数外部对其进行修改。

Yes, it has to do with the "stack." 是的,这与“堆栈”有关。 Specifically the "lifetime" of the function-local variable is only until the function ends. 特别是,函数局部变量的“生存期”仅直到函数结束为止。 And returning the pointer copies only the pointer and not what it points to, so you end up with a dangling pointer and undefined behavior. 并且返回指针仅复制指针,而不复制其指向的指针,因此最终会出现悬空指针和未定义的行为。

This is C++ after all, so the easiest thing to do here is simply make your function return std::string . 毕竟这是C ++,所以在这里最简单的事情就是让您的函数返回std::string That way it's a "value" rather than a pointer and returning it will make a copy (nb an optimizing compiler can elide the copy, but the functionality will remain the same). 这样,它是一个“值”,而不是一个指针,返回该值将创建一个副本(优化编译器可以删除该副本,但是功能将保持不变)。

Yes by returning str, you are returning an address of the stack memory that no longer exists. 是的,通过返回str,您将返回不再存在的堆栈存储器的地址。 The correct way of doing it is to allocate memory, pass it to fn, and then free it so that the same function is allocating and deallocating memory. 正确的做法是分配内存,将其传递给fn,然后释放它,以便同一功能分配和取消分配内存。

Using std::string will solve all your problems. 使用std::string将解决您的所有问题。 It's particularly strange that you use C++ streams but C-style strings. 使用C ++流但使用C风格的字符串特别奇怪。 Why? 为什么?

Here's what your code would look like: 您的代码如下所示:

#include <string>
#include <iostream>

std::string fn()
{
   std::string str = "Hello";
   std::cout << str; // This prints the string Hello perfectly
   // Some operations on string
   return str;
}

int main()
{
   std::string str = fn();
   std::cout << str;
}

This makes your code cleaner, more robust, exception-safe, easier to read and write and possibly faster. 这使您的代码更整洁,更健壮,异常安全,更易于读写,甚至可能更快。 Why in the world wouldn't you do it? 您为什么不这样做呢? (To be fair, there are situations where std::string isn't appropriate, but first, beginners rarely encounter them, and second, such situations typically also outrule C++ streams.) (公平地说,在某些情况下std::string是不合适的,但首先,初学者很少遇到它们,其次,这种情况通常也排除了C ++流。)

As for your original solution... 至于您的原始解决方案...

I know I should not pass address of a local variable back to main as that stack of the program is modified. 我知道我不应该在修改程序堆栈时将局部变量的地址传递回main。

Great :) But then why do you do it anyway? 太好了:)但是您为什么仍然要这样做呢?

But still if I use cout << *ptr then the output is just the first character "H" 但是,如果我使用cout << * * ptr,那么输出只是第一个字符“ H”

Besides the undefined behaviour resulting from returning a pointer to something that doesn't exist anymore, this sort of thing would happen even with a valid char* . 除了由于返回不再存在的指针而导致的不确定行为之外,即使使用有效的char*也会发生这种情况。 After all, dereferencing a char* is not different from dereferencing an int* or a double* . 毕竟,取消引用char*与取消引用int*double*是没有区别的。 It simply yields a char , and printing a char prints, well, a character. 它只是产生一个char ,而打印一个char打印一个字符。

int *i = new int(123);
std::cout << *i; // prints 123

double *d = new double(0.5);
std::cout << *d; // prints 0.5

char *c = new char('x');
std::cout << *c; // prints x

The fact that there may be more characters stored in memory right after that one dereferenced char is irrelevant. 在一个被取消引用的char之后,可能会在内存中存储更多字符这一事实是无关紧要的。 You deliver a char to std::cout , nothing more. 您将一个char传递给std::cout ,仅此而已。 If you deliver a char* , everything is different, because std::cout then knows that it must "look for more characters". 如果提供了char* ,那么一切都会有所不同,因为std::cout然后知道它必须“寻找更多字符”。

Again, using std::string , you don't need to care for these things. 同样,使用std::string ,您不需要关心这些事情。

I solved the problem by using a dynamically allocated memory for the array using "new". 我通过使用“ new”为数组使用动态分配的内存解决了该问题。

Not a good solution, because then you have the issue of who deletes the string. 这不是一个好的解决方案,因为这样会出现谁删除字符串的问题。 Without a delete[] somewhere at the right location in your code, the memory occupied by the string will never be released until your program terminates, which can lead to memory leaks and your end users wondering why YourProgram.exe suddenly takes 800 MB in the Windows Task Manager :) 如果在代码中正确位置的某个位置没有delete[] ,则直到程序终止,该字符串占用的内存才会释放,这可能导致内存泄漏,并且最终用户想知道为什么YourProgram.exe突然占用了800 MB内存。 Windows任务管理器:)

Again, use std::string . 同样, 使用std::string It frees the allocated memory automatically when it's no longer needed. 当不再需要分配的内存时,它将自动释放。

If you don't want to use std::string oder std::array, just basic C, change the function fn: 如果您不想使用std :: string或std :: array,而只是基本的C语言,请更改函数fn:

void fn(char *target, size_t target_size)
{
   if(target_size < 6)//I used 6 here because thats the size of the string you want write into the array
      return; //If the targets size is to small, the function is cancled
   strycpy(target, "Hello");
   cout << target;
}

int main()
{
   char str[20];
   fn(str, 20);
   std::cout << str;
}

But it generall its better to use std::string as shown above, because this method is unsafe ( Your program will crash if you make target_size bigger then the real size of the array, beause strcpy will write over the arrays limit). 但是一般最好使用上面所示的std :: string,因为这种方法是不安全的(如果将target_size设置为大于数组的实际大小,则程序将崩溃,因为strcpy将覆盖数组限制)。 Some compilers won't even allow to use this, because of "strcpy". 由于“ strcpy”,某些编译器甚至不允许使用此功能。

Another (uncommon) possibility would be to make the array static: 另一种(不常见的)可能性是使数组静态:

char * fn(void)
{
   static char str[20] = "Hello";
   cout << str;
   return str;
}

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

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