在谈述函数调用和返回值问题之前,先来看看c++中内存分配的问题。
内存分配的问题:
int a=1; a在栈区
char s[]="123"; s在栈区,“123”在栈区,其值可以被修改
char *s="123"; s在栈区,“123”在常量区,其值不能被修改
int *p=new int; p在栈区,申请的空间在堆区(p指向的区域)
int *p=(int *)malloc(sizeof(int)); p在栈区,p指向的空间在堆区
static int b=0; b在静态区
1.test1
#include<iostream>
using namespace std;
void test(int *p)
{
int b=2;
p=&b;
cout<<p<<endl;
}
int main(void)
{
int a=10;
int *p=&a;
cout<<p<<endl;
test(p);
cout<<p<<endl;
return 0;
}
第一行输出和第三行输出的结果相同,而第一行、第三行与第二行输出的结果不同。从这里可以看出,当指针作为参数进行传递时传递的也只是一个值,只不过该值只一个地址,因此对于形参的改变并不影响实参。
2.test2
#include<iostream>
using namespace std;
char* test(void)
{
char str[]="hello world!";
return str;
}
int main(void)
{
char *p;
p=test();
cout<<p<<endl;
return 0;
}
输出结果可能是hello world!,也可能是乱麻。
出现这种情况的原因在于:在test函数内部声明的str数组以及它的值"hello world”是在栈上保存的,当用return将str的值返回时,将str的值拷贝一份传回,当test函数执行结束后,会自动释放栈上的空间,即存放hello world的单元可能被重新写入数据,因此虽然main函数中的指针p是指向存放hello world的单元,但是无法保证test函数执行完后该存储单元里面存放的还是hello world,所以打印出的结果有时候是hello world,有时候是乱麻。
3.test3
#include<iostream>
using namespace std;
int test(void)
{
int a=1;
return a;
}
int main(void)
{
int b;
b=test();
cout<<b<<endl;
return 0;
}
输出结果为 1
有人会问为什么这里传回来的值可以正确打印出来,不是栈会被刷新内容么?是的,确实,在test函数执行完后,存放a值的单元是可能会被重写,但是在函数执行return时,会创建一个int型的零时变量,将a的值复制拷贝给该零时变量,因此返回后能够得到正确的值,即使存放a值的单元被重写数据,但是不会受到影响。
4.test4
#include<iostream>
using namespace std;
char* test(void)
{
char *p="hello world!";
return p;
}
int main(void)
{
char *str;
str=test();
cout<<str<<endl;
return 0;
}
执行结果是 hello world!
同样返回的是指针,为什么这里会正确地打印出hello world1?这是因为char *p="hello world!",指针p是存放在栈上的,但是"hello world!”是一个常量字符串,因此存放在常量区,而常量区的变量的生存期与整个程序执行的生命期是一样的,因此在test函数执行完后,str指向存放“hello world!”的单元,并且该单元里的内容在程序没有执行完是不会被修改的,因此可以正确输出结果。
5.test5
#include<iostream>
using namespace std;
char* test(void)
{
char *p=(char *)malloc(sizeof(char)*100);
strcpy(p,"hello world");
return p;
}
int main(void)
{
char *str;
str=test();
cout<<str<<endl;
return 0;
}
运行结果 hello world
这种情况下同样可以输出正确的结果,是因为是用malloc在堆上申请的空间,这部分空间是由程序员自己管理的,如果程序员没有手动释放堆区的空间,那么存储单元里的内容是不会被重写的,因此可以正确输出结果。
6.test6
#include<iostream>
using namespace std;
void test(void)
{
char *p=(char *)malloc(sizeof(char)*100);
strcpy(p,"hello world");
free(p);
if(p==NULL)
{
cout<<"NULL"<<endl;
}
}
int main(void)
{
test();
return 0;
}
没有输出
在这里注意了,free()释放的是指针指向的内存!注意!释放的是内存,不是指针!这点非常非常重 要!指针是一个变量,只有程序结束时才被销毁。释放了内存空间后,原来指向这块空间的指针还是存在!只不过现在指针指向的内容的垃圾,是未定义的,所以说是垃圾。因此,释放内存后应把把指针指向NULL,防止指针在后面不小心又被使用,造成无法估计的后果