我在一个函数中有一个局部字符数组,该函数根据函数中的逻辑进行操作。该函数将指针返回到数组,如下所示
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
}
如何将数组从函数传递回main。
我知道我不应该将本地变量的地址传递回main,因为该程序的堆栈已被修改。但是如果我使用cout&lt;&lt; * ptr然后输出只是第一个字符“H”。我通过使用“new”为数组使用动态分配的内存来解决问题。但我想知道这种行为背后的原因(这是否必须与Stack做些什么)
答案 0 :(得分:2)
如果你在函数中创建数组的方式,那就是在堆栈上创建的契约,当你离开函数时它将被销毁。 通过函数操作数组的常用方法是将指针作为函数参数传递给已存在的数组。当你在函数中修改它时,它也将在函数外修改。
答案 1 :(得分:2)
是的,它与&#34;堆栈有关。&#34;特别是&#34;生命周期&#34;函数局部变量只在函数结束之前。并且返回指针只复制指针而不是它指向的指针,因此你最终得到一个悬空指针和未定义的行为。
毕竟这是C ++,所以最简单的方法就是让函数返回std::string
。这样它就是一个&#34;价值&#34;而不是指针并返回它将进行复制(n.b.优化编译器可以删除副本,但功能将保持不变)。
答案 2 :(得分:2)
是的,通过返回str,您将返回不再存在的堆栈内存的地址。正确的方法是分配内存,将其传递给fn,然后释放它,以便相同的功能分配和释放内存。
答案 3 :(得分:1)
使用std::string
将解决您的所有问题。你使用C ++流但C风格的字符串特别奇怪。为什么呢?
以下是您的代码的样子:
#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;
}
这使您的代码更清晰,更强大,异常安全,更易于读写,并且可能更快。你为什么不在世界上呢? (公平地说,有些情况std::string
不合适,但首先,初学者很少遇到它们,其次,这种情况通常也会使C ++流不存在。)
至于你原来的解决方案......
我知道我不应该将局部变量的地址传回main 该程序的堆栈被修改。
很棒:)但是你为什么要这样做呢?
但是如果我使用cout&lt;&lt; * ptr然后输出就是第一个 字符“H”
除了将指针返回到不再存在的东西所导致的未定义行为之外,即使使用有效的char*
,也会发生这种情况。毕竟,取消引用char*
与解除引用int*
或double*
没有什么不同。它只是产生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
在一个解除引用char
之后可能有更多字符存储在内存中的事实是无关紧要的。您只需向char
发送std::cout
即可。如果您提供char*
,则一切都不同,因为std::cout
然后知道它必须“寻找更多字符”。
再次,使用std::string
,您无需关心这些事情。
我通过使用动态分配的内存来解决问题 数组使用“new”。
不是一个好的解决方案,因为那时你有谁删除字符串的问题。在代码中的正确位置没有delete[]
的情况下,字符串占用的内存将永远不会释放,直到程序终止,这可能导致内存泄漏,最终用户想知道为什么YourProgram.exe突然占用800 MB在Windows任务管理器中:)
再次,使用std::string
。它不再需要时自动释放分配的内存。
答案 4 :(得分:0)
如果您不想使用std :: string oder 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;
}
但是如上所示,通常使用std :: string更好,因为这种方法不安全(如果你使target_size大于数组的实际大小,你的程序会崩溃,因为strcpy将覆盖数组限制) 。有些编译器甚至不允许使用它,因为&#34; strcpy&#34;。
另一种(不常见的)可能是使数组静态:
char * fn(void)
{
static char str[20] = "Hello";
cout << str;
return str;
}