关于C++的返回临时对象指针的疑问

chenguangw 2006-05-13 04:35:40
char *f()
{
char s[]="HELLO";
return s;
}

char *f1()
{
char *p=NULL;
char s[]="world";
p=s;
return p;
}

int *f2()
{
int *p;
int i = 32;
p = &i;
return p;
}


void main()
{
cout << f() << endl;
cout << f1() << endl;
cout << *f2() << endl;

return;

}

f()种申明的s为临时变量。函数返回后s就释放了,所以main函数输出的是乱码。

f1()申明的指针p指向的是局部变量s,函数返回后,s释放,所以main输出的也是乱码。

f2()按我的理解p也指向的时局部变量i,i在函数结束后也应该释放掉,我设想最后在main中输出的同样是乱码,但事实恰恰相反,在vc60的环境下我编译后,程序正常输出了32。很让我费解。

...全文
477 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
chenguangw 2006-05-16
  • 打赏
  • 举报
回复
谢谢大家,其实原理估计大家也都明白,但就是很疑惑为啥结果是这样的.今天结帖.
chenguangw 2006-05-16
  • 打赏
  • 举报
回复
昨天没来就又有了这么回答,谢谢大家.
学习ing
塘外人 2006-05-15
  • 打赏
  • 举报
回复
有点懂了,,
其实我觉得我们不必要讨论输出的到底是什么,,
知道原理及后果才是最重要的,,
你们说呢/?
0黄瓜0 2006-05-14
  • 打赏
  • 举报
回复
栈内存的管理和我们使用数据结构栈是类似的,比如一个简单的数据结构栈可以定义为
class Stack
{
int top;
long elem[20];
Stack()
{top==-1;}
void push(long e)
{elem[++top]=e;}
long pop()
{return elem[top--];}
};
当我们push一些数据,然后pop数据的时候,只须简单将栈顶指针top减1,无需覆盖那个数据,虽然在重新push数据前,也还能通过一些方法访问到先前的数据,但是,当你不能控制什么时候会push数据,那么你访问到的数据是不可靠的。 返回局部变量的指针就象返回这个已经pop的数据的指针,能不能访问有效数据是不一定的。
yjsoft 2006-05-14
  • 打赏
  • 举报
回复
我说错了,算我没说
yjsoft 2006-05-14
  • 打赏
  • 举报
回复
楼主的三个函数都是从栈分配的,声明期就是函数执行完以前。如果需要返回指针,必须从堆分配。但不赞成在函数内部new,那样会造成歧义。调用者不知道该不该释放它。
mianwo602 2006-05-14
  • 打赏
  • 举报
回复
int *f2()
{
int *p;
int i = 32;
p = &i;
return p;
}
void main()
{
char* p = f1();
int *a = f2(); //我将你写的改了下
char* q = f3();

cout << p << " " << *a << " " << q << endl;

return ;

}
结果就不是32了
你先是int a=*f2(); 这时你已经将值返回a=32;
而我该成int *a = f2();这样是返回的地址,这时i被释放了,值就不是32了
ericqxg007 2006-05-14
  • 打赏
  • 举报
回复
上面的错了点 输出a的时候是内存地址了
这样改
cout << p << " " << *a << " " << q << endl;
结果是:0繤 7567215 €
ericqxg007 2006-05-14
  • 打赏
  • 举报
回复
#include <iostream>
using namespace std;

char *f1()
{
char *p=NULL;
char s[]="windows";
p=s;
return p;
}

int *f2()
{
int *p;
int i = 32;
p = &i;
return p;
}

char *f3()
{
char *p=NULL;
char s[]="System";
p=s;
return p;
}

void main()
{
char* p;

int *a ;
char* q;
a = f2();
q = f3();
p = f1();
cout << p << " " << a << " " << q << endl;

return ;

}

改变了一下函数调用的顺序 你看看结果
我的结果是 0繤 0012FF18 €
mianwo602 2006-05-14
  • 打赏
  • 举报
回复
return语句不可返回指向栈内存的指针和引用,因为该内存在函数体结束时别自动销毁
mianwo602 2006-05-14
  • 打赏
  • 举报
回复
哎, 还是不能理解
猜下面的代码在vc2005中输出什么?
char *f1()
{
char *p=NULL;
char s[]="windows";
p=s;
return p;
}

int *f2()
{
int *p;
int i = 32;
p = &i;
return p;
}

char *f3()
{
char *p=NULL;
char s[]="System";
p=s;
return p;
}

void main()
{
char* p = f1();
int a = *f2();
char* q = f3();

cout << p << " " << a << " " << q << endl;

return ;

}

是不折不扣的:windows 32 System
汗!~~~

我运行了的不是上面的 ,乱吗 32 乱吗
ericqxg007 2006-05-14
  • 打赏
  • 举报
回复
如果真如ericqxg007(卡卡一笑而过)所说的那样的,但yhmhappy2006() 给出的代码我测试了一下仍然是int*正常返回了,而char*的函数是乱码。ericqxg007(卡卡一笑而过)能不能给出一段代码呢?
//函数返回后,对应的临时内存空间会被释放,这个我想楼主没有疑问吧?
但是对应的内存空间什么时候会被修改那就得看具体系统运行环境了(也就是说要看你当时应用程序使用内存的情况)。给出了代码,对应的运行环境不同,那所得到的结果也会不相同。


下面从编译器的角度来说说这个函数调用返回后对应的临时内存空间释放的问题。
一般编译器对于调用函数都会形成一个特殊的栈(我们称之为函数栈)来保存该函数的信息, 如返回值,函数参数,函数内部定义的变量等等。当函数调用结束的时候编译器便会将该函数pop出函数栈,那么在函数内部定义的变量都会被我们理解为已经释放。这个使用和我们常用的stack操作也一样。
所以当你调用某函数并返回临时内存空间的地址时,编译器并不保证以后的函数调用会修改原来内存区域的内容,所以你有可能通过该函数返回的地址来取得对应地址的内容(内容可能一直没有改变)。所以,就得到了lz你所得到的结果。

现在明白了吧?
塘外人 2006-05-13
  • 打赏
  • 举报
回复
为什么我的就是:windows 32 System 呢?

搞不懂了, 我也是vc2005啊
tatbaby 2006-05-13
  • 打赏
  • 举报
回复
to yhmhappy2006() :
vc7
统A 32 ?

gcc4.10
↔▼ 32 ▼
chenguangw 2006-05-13
  • 打赏
  • 举报
回复
会不会是内部类型如int之类的是特例呢,和编译器有关?
chenguangw 2006-05-13
  • 打赏
  • 举报
回复
楼上的代码,我测试了一下。
也是在vc2005下面编译调试的。
但不知道为什么我的输出结果不是“windows 32 System”,而是“h 32”,好像还是只有f2()正确的返回了。

我通过反复测试发现,当返回的指针指向的临时对象是int、float类型时,返回的数据没有问题。但是临时对象是自定义的类型或者char*的时候就会有问题。

资料上说,从函数中返回临时对象会拷贝到一个保存返回值的外部存储单元中。这个存储单元的作用域应该是调用函数的地方,如果返回的是一个指针那么指针所指向的如果是个临时变量,当这个临时变量被释放后,内存中应该是乱码,char* f()和char* f1()的结果和预期一样,但int *f2()就不对了。
如果真如ericqxg007(卡卡一笑而过)所说的那样的,但yhmhappy2006() 给出的代码我测试了一下仍然是int*正常返回了,而char*的函数是乱码。ericqxg007(卡卡一笑而过)能不能给出一段代码呢?
塘外人 2006-05-13
  • 打赏
  • 举报
回复
哎, 还是不能理解
猜下面的代码在vc2005中输出什么?
char *f1()
{
char *p=NULL;
char s[]="windows";
p=s;
return p;
}

int *f2()
{
int *p;
int i = 32;
p = &i;
return p;
}

char *f3()
{
char *p=NULL;
char s[]="System";
p=s;
return p;
}

void main()
{
char* p = f1();
int a = *f2();
char* q = f3();

cout << p << " " << a << " " << q << endl;

return ;

}

是不折不扣的:windows 32 System
汗!~~~
tatbaby 2006-05-13
  • 打赏
  • 举报
回复
参考:
http://community.csdn.net/Expert/topic/4749/4749626.xml?temp=.2227289
tatbaby 2006-05-13
  • 打赏
  • 举报
回复
yhmhappy2006() ( ) 信誉:100 2006-05-13 19:11:00 得分: 0


///输出32并不代表那个局部变量的内存空间没有释放 只是该内存单元没有被修改内容而已

请问在什么情况下会修改?


======================================================
当有数据写入时。比如再main或者其他函数中再定义定量时,原来的临时空间已经被回收,
并且新的变量可能覆盖了以前的空间。
塘外人 2006-05-13
  • 打赏
  • 举报
回复
///输出32并不代表那个局部变量的内存空间没有释放 只是该内存单元没有被修改内容而已

请问在什么情况下会修改?
加载更多回复(2)

64,648

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧