我们说C++的内存结构为栈,堆,全局变量域,其中全局变量域中存放global变量,static变量和常量,栈中存放运行时候的函数以及局部变量,堆中存放程序中用new生成的对象,那么程序的函数返回的局部变量与C++的内存分配有什么关系呢?下面请看如下代码,对比思考:
a.cpp
#include <iostream>
#include <string>
using namespace std;
class Hello{
public:
Hello(){
}
Hello(int x, int y) :x(x), y(y){
}
Hello(Hello& h){
this->x = h.x;
this->y = h.y;
}
Hello& operator=(const Hello& h){
this->x = h.x;
this->y = h.y;
return *this;
}
friend ostream& operator<<(ostream& os, Hello& hel){
os << hel.x << " " << hel.y << endl;
return os;
}
void show(){
cout << x << " " << y << endl;
}
friend Hello* createHello(Hello& hello){
try{
Hello *hel = new Hello();
hel->x = hello.x;
hel->y = hello.y;
return hel;
}
catch (exception &e){
cout << e.what() << endl;
}
return NULL;
}
~Hello(){
}
private:
int x;
int y;
};
int* h1(){
int m = 9;
return &m;
}
int main(){
Hello h1(10, 10);
Hello *h2 = createHello(h1);
cout << *h2 << endl;
delete h2;
return 0;
}
运行结果为:
代码变更呢?结果会怎样呢?
a2.cpp
#include <iostream>
#include <string>
using namespace std;
class Hello{
public:
Hello(){
}
Hello(int x, int y) :x(x), y(y){
}
Hello(Hello& h){
this->x = h.x;
this->y = h.y;
}
Hello& operator=(const Hello& h){
this->x = h.x;
this->y = h.y;
return *this;
}
friend ostream& operator<<(ostream& os, Hello& hel){
os << hel.x << " " << hel.y << endl;
return os;
}
void show(){
cout << x << " " << y << endl;
}
friend Hello* createHello(Hello& hello){
try{
Hello temp(hello);
return &temp;
}
catch (exception &e){
cout << e.what() << endl;
}
return NULL;
}
~Hello(){
}
private:
int x;
int y;
};
int* h1(){
int m = 9;
return &m;
}
int main(){
Hello h1(10, 10);
Hello *h2 = createHello(h1);
cout << *h2 << endl;
delete h2;
return 0;
}
结果如下:
我们可以很清楚的看到,此时这个程序返回的值是随机数,并不是我们想要的,那么问题处在哪里呢?
经过对比,可以发现a.cpp中我们创建了一个临时对象Hello *hel,hel指向new 在堆中分配的地址,当函数结束时候,局部变量为hel指针而已,被返回保存到主程序中的寄存器中,函数中的hel指针被销毁而已,创建的对象仍旧在堆中,因此当我们访问的时候,可以找到堆中的信息,然后加以输出,最后通过delete hel销毁掉堆中的对象,很通顺的一个过程;
a2.cpp中我们通过copy构造函数创建了一个Hello temp临时变量,这个对象的全部都在函数栈中,由于有析构函数,在结束函数调用的时候,临时对象被销毁,主程序的寄存器中保留了一个指针,指向的那个对象已经被析构函数销毁,因此访问的时候找不到所以出现随机数! 有朋友问按照这个思路的话,这个问题怎么解?
int* h1(){
int m = 9;
return &m;
}
int& h2(){
int m = 9;
return m;
}
int main(){
int* h1_ptr=h1();
int hh2=h2();
cout << *h1_ptr << endl;
hh2 = 100;
cout << hh2 << endl;
return 0;
}
运行结果为:
相同的问题也适用于全局变量域,效果如下:
char *h2(){
int m = 9;
char s[] = "hello";
return s;
}
int main(){
char *s = h2();
cout << s << endl;
return 0;
}
运行结果:
char *h2(){
int m = 9;
char s[] = "hello";
return s;
}
int main(){
char *s = h2();
cout << s << endl;
return 0;
}
运行结果:
可以看到,竟然局部变量的值没有被销毁,什么鬼?哈哈,不要纠结啦,兄弟,
因为这些局部变量都是基本类型,没有析构函数,程序在执行栈顶的时候没有执行别的栈操作,因此这些变量值暂时还在栈中,其实是编译器懒得彻底销毁,在别的栈操作未执行时,而基本类型没有析构函数,编译器就想偷个懒,暂时让其存在一下,直到有新的栈操作发生时候才覆盖,因此,不要太纠结呀
,祝大家在C++的大坑中越走越顺!!!路漫漫兮其修远兮,吾将上下而求索!!!