如何在 C++ 中返回本地数组?
Posted
技术标签:
【中文标题】如何在 C++ 中返回本地数组?【英文标题】:How to return local array in C++? 【发布时间】:2011-12-07 20:56:38 【问题描述】:char *recvmsg()
char buffer[1024];
return buffer;
int main()
char *reply = recvmsg();
.....
我收到警告:
警告 C4172:返回局部变量或临时地址
【问题讨论】:
您应该选择 C 或 C++,因为一个好的答案将取决于此。 你想要 C++ 的答案还是只想要 C 的答案? 哦,顺便说一句。void main
错了。
如果你正在学习 C++ 的东西使用 void main
,那很可能是废话。我会推荐a good introductory C++ book。
在调用例程中使用*recvmsg
only 的返回作为像strcpy
这样的函数的输入的情况下,可以忽略警告,如函数 return 没有在赋值中使用。
【参考方案1】:
我建议std::vector<char>
:
std::vector<char> recvmsg()
std::vector<char> buffer(1024);
//..
return buffer;
int main()
std::vector<char> reply = recvmsg();
然后,如果您的代码中需要char*
,那么您可以随时使用&reply[0]
。例如,
void f(const char* data, size_t size)
f(&reply[0], reply.size());
你就完成了。这意味着,如果您使用的是 C API,那么您仍然可以使用 std::vector
,因为您可以将 &reply[0]
传递给 C API(如上所示),并将 reply
传递给 C++ API。
底线是:尽可能避免使用new
。如果你使用new
,那么你必须自己管理它,当你不需要它的时候你必须delete
。
【讨论】:
呵呵,OP 确实投票支持c++,所以应该是这样 OP 也可以使用std::string
。
@ThomasMatthews:如果您将数据(char*
类型)概念化为 buffer 而不是 string,那么我相信 @ 987654334@ 比std::string
更清楚地传达了这一点。
.. 或者可以使用using buffer_t = std::vector<char>;
(或者可能是using buffer_t = std::string;
),然后使用buffer_t
;也许这样更合适。 (希望 C++ 有 strong 别名!)【参考方案2】:
你需要动态分配你的 char 数组:
char *recvmsg()
char* buffer = new char[1024];
return buffer;
对于 C++ 和
char *recvmsg()
char* buffer = malloc(1024);
return buffer;
对于 C.
如果没有动态分配,您的变量将驻留在函数的堆栈中,因此会在退出时被销毁。这就是你收到警告的原因。在堆上分配它可以防止这种情况发生,但你必须小心并通过delete[]
释放内存。
【讨论】:
在 C++ 中使用new
并不能使其成为 C++ 风格的解决方案。 C++ 风格的解决方案是std::vector<char>
,而不是原始指针char*
。
据我所知,如果您对 c# 或 VB 有任何互操作需求,您不能真正将 std::vector 与 p/invoke 一起使用
malloc( 1024 * sizeof( char ) )
不是更好吗?
@sazary 偏好问题,sizeof char 始终为 1。
没必要,用的是malloc,看karl or mine的回答。【参考方案3】:
警告信息是正确的。您正在返回函数返回后消失的本地数组的地址。
您可以使用动态内存分配来做到这一点:
char *recvmsg()
char *buffer = (char*)malloc(1024);
return buffer;
需要注意的是,您需要确保您稍后使用 free()
指针以避免内存泄漏。
或者,您可以将缓冲区传递给函数。
void recvmsg(char *buffer,int buffer_size)
// write to buffer
void main()
char buffer[1024];
recvmsg(buffer,1024);
这避免了内存分配的需要。这实际上是首选的方法。
【讨论】:
我肯定会不建议这个。在 C++ 中,std::vector<char>
是更好的解决方案。这个答案建议使用 C 风格的解决方案,但问题是用 C++ 标记的。
为什么我的印象是它被标记为 C...但是是的,你是对的,矢量是首选。【参考方案4】:
问题是buffer
存在于堆栈中,并在您退出recvmsg
时超出范围。
你可以在堆上分配buffer
:
char *recvmsg()
char *buffer = malloc(1024);
return buffer;
请注意,现在调用者负责处理分配的内存:
void main()
char *reply = recvmsg();
free(reply);
【讨论】:
大部分答案都是有效的,但只有你提到了 free()。为了便于阅读,我会在 main() 中的两行之间添加注释:/* do stuff here*/
。 +1【参考方案5】:
您有几个选择...您现在的操作方式将导致未定义的行为,因为一旦 hte 函数返回,数组将超出范围。所以一种选择是动态分配内存..
char * recmsg()
char * array = new char[128];
return array;
请记住以这种方式删除它(或者如果您使用 malloc,则免费)。其次,您可以使用参数...
void recmsg(char * message, int size)
if (message == 0)
message = new char[size];
同样,这里的清理与之前的相同。还要注意检查 0 以确保您不会在已分配的指针上调用 new。
最后,你可以使用矢量..
std::vector<char> recmsg()
std::vector<char> temp;
//do stuff with vector here
return temp;
【讨论】:
【参考方案6】:char *recvmsg()
char *buffer = new char;
cout<<"\nENTER NAME : ";
cin>> buffer;
return buffer;
int main()
char *reply = recvmsg();
cout<<reply;
【讨论】:
【参考方案7】:只是为了完成图片:
没有必要用 malloc 分配内存。您也可以在堆栈上创建缓冲区,但您必须在堆栈帧上创建它,只要缓冲区的使用者存在。那是 OP 的错误——当被调用者完成时,缓冲区被删除并且调用者得到了一个无效的指针。
所以你可以这样做:
void recvmsg(char *buffer, size_t size)
... do what you want ...
void main(void)
char buffer[1024];
recvmsg(buffer, sizeof(buffer));
【讨论】:
【参考方案8】:您可以动态创建缓冲区,但调用者需要知道释放它。
我认为最好传入一个缓冲区(假设 recvmsg 也填充它)
void recvmsg(char *buffer, size_t size)
void main()
char buffer[1024];
recvmsg(buffer, sizeof(buffer));
即使调用者认为动态更好,他们也会知道他们需要释放它,以及执行此操作的具体方法(free()、delete、delete[],或者可能来自自定义分配器的特殊方法)
【讨论】:
【参考方案9】:问题是您正在返回一个指向在堆栈上分配的缓冲区的指针。一旦函数返回,该缓冲区就不再有效。
【讨论】:
【参考方案10】:您在 recvmsg
函数内部的堆栈上分配数组。如果取消引用,返回指向该内存的指针将在某些时候导致未定义的行为,因为当函数退出时内存将被清理。
如果你想返回一个指向内存的指针,你需要使用malloc
动态分配它。
【讨论】:
【参考方案11】:当您返回缓冲区时,因为它充当指向数组第一个位置的指针,因此它将返回其地址。在您在那里调用函数的地方,您可以创建一个字符指针来存储它返回地址值。之后您可以移动指针并访问数组的所有元素。
【讨论】:
【参考方案12】:通过 ref 怎么样
char buf[1024];
PutStuffInBuff(&buf);
【讨论】:
我猜,karl 的意思是调用者正在提供对 buf 的引用,而被调用者正在填充 buf。因为调用者作为被调用者的寿命更长(buf 也是如此,所以一切正常,只要调用者不返回 buf 的引用)。以上是关于如何在 C++ 中返回本地数组?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 ctypes 将数组从 C++ 函数返回到 Python