C++函数返回值问题
文章目录
调用函数的过程
栈空间是从高地址向低地址增长的。所以压栈即表示栈顶指针变小,而出栈则相反。
函数调用者维护了一个栈空间(stack),拥有栈底指针ebp和栈顶指针esp。
调用函数时,栈变化过程简单描述如下:
1)先将函数返回地址ret压栈,即函数执行完毕后将从哪里继续执行下去
2)将ebp压栈
3)将esp赋值给ebp
4)将函数局部变量压栈
函数执行完毕后,栈变化过程如下:
1)函数局部变量出栈
2)ebp出栈,恢复ebp的值
3)函数返回地址出栈
从以上的变化过程可以看到,函数调用者通过操作ebp和esp的值变化来维护栈的变化。
函数返回局部变量
一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。
可以有两种情况:返回局部自动变量和局部静态变量
局部自动变量
|
|
局部变量temp存储在栈中,函数返回时会自动复制一份temp的copy给调用者,没有问题
|
|
返回的是v的值拷贝,没有问题。
|
|
返回的也是值拷贝,会调用Person类的拷贝构造函数,没有问题。
静态局部变量
|
|
局部变量a存储在静态(全局)存储区中,从初始化后一直有效直到程序结束,仅分配一次内存,并且函数返回后,变量不会销毁,没有问题。
函数返回指针
函数返回指针其实就是返回指针指向的地址,只要地址不会失效,那么返回的指针就一直有效。
指针指向的是局部变量
可以有两种情况:返回局部自动变量和局部静态变量
局部自动变量
虽然函数执行完毕后栈“销毁”了,但在重入之前,存储在栈中的局部变量仍然存在!这个时候,通过指针来访问该位置仍然可以获得正确的值!
|
|
静态局部变量
|
|
局部变量temp存储在静态存储区,返回指向静态存储区变量的指针是可行的。
字符串
|
|
对于字符串的特殊情况,由于字符串test存储在常量存储区(不是静态存储区),因此函数返回一个指向常量的字符串指针是可行的。
|
|
这种情况下,str被初始化为字符串局部变量,因此函数返回一个已销毁的局部变量是不可行的。
指向局部自动变量的方法
利用new或malloc使变量在堆中存放。这种情况下,函数返回一个指向堆内存的指针,由于堆存储区由程序员手动管理,因此这种做法是可行的,但是要防止出现内存泄露,函数调用完后需要手动释放内存。这里的sizeof作用于指针返回的是指针类型的长度1byte,而如果作用于数组返回的则是数组的长度。
|
|
指针指向的是参数或NULL
指针指向其中一个参数或NULL,是可以的。
ListNode *mergeTwoLists(ListNode *l1, ListNode *l2) { if (l1 == NULL) return l2; if (l2 == NULL) return l1; ListNode *ret = NULL; if (l1->val < l2->val) { ret = l1; ret->next = mergeTwoLists(l1->next, l2); } else { ret = l2; ret->next = mergeTwoLists(l1, l2->next); } return ret; }
函数返回引用
引用和指针基本一致,唯一的不同是引用不能返回NULL
文章作者 Forz
上次更新 2017-06-23