精华内容
下载资源
问答
  • 否则结果可能正确,但存在风险。跳出函数后,局部变量已经没有作用域,受控了,可能内存又分配给别的变量,内容被修改。

    否则结果可能正确,但存在风险。跳出函数后,局部变量已经没有作用域,不受控了,可能内存又分配给别的变量,内容被修改。

    展开全文
  • 参考:《C语言程序设计(苏小红)》P334-351 动态内存分配 char *strA() {  char str[] = "hello word";  return str;...简单的来说,str是个局部变量的地址,...局部变量作为返回值时,一般是系统先申请一个临时...

    参考:《C语言程序设计(苏小红)》P334-351  动态内存分配

    char *strA()

    {

      char str[] = "hello word";

      return str;

    }

    上述程序有什么问题?

    简单的来说,str是个局部变量的地址,作为返回值,有可能被提前回收。

    那么局部变量可以作为函数的返回值吗,这个问题不能一概而论。局部变量作为返回值时,一般是系统先申请一个临时对象存储局部变量,也就是找个替代品,这样系统就可以回收局部变量,返回的只是个替代品。

    了解完局部变量返回的过程,那么如果返回的是一个基本类型的变量,比如:

    int a;

    a = 5;

    return a;

    那么就会有一个临时对象也等于a的一个拷贝,即5返回,然后a就被销毁了。尽管a被销毁了,但它的副本5还是成功地返回了,所以这样做没有问题。

    那么如果是指针,这么返回就问题很大,因为你返回的局部变量是地址,地址虽然返回了,但地址所指向的内存中的值已经被回收了,你主函数再去调,就有问题了。这个问题也是可以解决的,可以把局部变量变为静态变量或者全局变量,这样就不存放在栈中了,而是存放在静态存储区,不会被回收。

     

    char str[] = "hello word";//分配一个局部变量

    char *str= "hello word";//分配一个全局变量

    展开全文
  • golang 局部变量地址作为返回值的问题 func createNode(v int) *node{ return &node{value:v} } func main(){ var root *node root=createNode(10) ... } 在c/c++语言中,以上的代码逻辑显然有问题,...

    golang 局部变量地址作为返回值的问题

    func createNode(v int) *node{
    	return &node{value:v} 
    }
    
    func main(){
    	var root *node
    	root=createNode(10)
    	...
    }
    

    在c/c++语言中,以上的代码逻辑显然有问题,createNode函数中创建了一个局部变量(空间分配在栈上),并将其地址返回。但是当函数退出后 该局部变量被回收,因此函数返回的地址显然无效的。


    但是在go语言中这么做是可以正常使用的。


    原因即go语言编译器会做逃逸分析(escape analysis),自动决定把一个变量分配在栈上还是堆上,当发现变量的作用域没有跑出函数范围,就在栈上,反之则必须分配在堆上。


    需要注意的是,对于动态new出来的局部变量,编译器也会根据是否有逃逸行为来决定是分配在堆还是栈,而并非直接分配在堆中。


    参见:

    How do I know whether a variable is allocated on the heap or the stack?
    
    From a correctness standpoint, you don not need to know. Each variable in Go exists as long as there are references to it. The storage location chosen by the implementation is irrelevant to the semantics of the language.
    
    The storage location does have an effect on writing efficient programs. When possible, the Go compilers will allocate variables that are local to a function in that function's stack frame. However, if the compiler cannot prove that the variable is not referenced after the function returns, then the compiler must allocate the variable on the garbage-collected heap to avoid dangling pointer errors. Also, if a local variable is very large, it might make more sense to store it on the heap rather than the stack.
    
    
    展开全文
  • 最重要的一点:函数不能返回指向栈内存的指针! 为什么?因为返回的都是值拷贝!  一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果...

    最重要的一点:函数不能返回指向栈内存的指针!

    为什么?因为返回的都是值拷贝!

            一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不涉及地址,程序不会出错。但是如果返回的是局部变量的地址(指针)的话,程序运行后会出错。因为函数只是把指针复制后返回了,但是指针指向的内容已经被释放了,这样指针指向的内容就是不可预料的内容,调用就会出错。准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。

           我们知道,局部变量的作用域是函数内部,函数一旦执行结束,栈上的局部变量会进行销毁,内存得到释放。因此,此时函数返回的是该局部变量的值拷贝,这是没有问题的。但是如果返回的是局部变量的地址,那么返回的只是该局部变量指针的拷贝,而随着函数运行结束,该拷贝指针所指向的栈内存已经被释放,那么指向一个未知区域就会导致调用的错误。

          那如果返回的指针指向的是堆内存,又会怎么样?

          这样的使用是没有问题的,在函数内new空间,在函数外delete空间。但是这样并不是一种好的编程风格,尽量在同一个作用域内进行new和delete操作,否则还要调用者手动进行内存的释放,试问这样的接口是不是很烂。如果确实需要这样做,那就传指针进去吧!

    #include "fun_stdy.h"
    #include <iostream>
    using namespace std;
     
    int return_value0(){	
    	int ret = 0;
    	cout << " in return_value0 , address and value:"<< &ret <<" "<< ret <<endl;
     
    	return ret;		//ok 最常见的情况, 返回局部变量的副本
    }
     
    int* return_value1()  
    {  
    	int ret=1;  
    	cout << " in return_value1 ,  and value:"<< &ret<<" " << ret <<endl;
     
    	return &ret;	//error 虽然value被释放 , 但里面的值可能不会被清除,所以有时候你这么用
    					//看起来结果好像也是对的,但是隐患无穷。
    } 
     
    int* return_value2()  
    {  
    	int *ret = new int(2); 
    	cout << " in return_value2 , address and value:"<< &ret <<" " << ret <<endl;
     
    	return ret;  //ok 在函数内申请空间,调用后需要调用者手动在函数外释放空间
    } 
    int* return_value3(int *ret)		//指针value不能为null,否则报错
    {  
    	ret = new int(3);  
    	cout << " in return_value3 ,  address and value:"<< &ret<<" " << ret <<endl;
     
    	return ret;  //ok 在函数内申请空间,调用后需要调用者手动在函数外释放空间
    } 
     
    char *return_value4()
    {
    	char p[] = "hello world";
    	cout << " in return_value4 ,  address and value:"<< &p<<" " << p <<endl;
     
    	return p;    //p[]数组为函数内部局部变量,在函数返回后,内存已经被释放了,
    	//所以在主函数中调用该函数str2 = return_value3();输出的可能为乱码
    }
     
    //此函数中p也是个局部变量,函数执行完自动销毁,但是指针分配的空间不会被自动回收,除非程序员delete掉。
    //所以这个可以正常输出。
    char *return_value5()
    {
    	char *p = "hello world";//这个初始化的一种形式,相当于分配了sizeof(hello world)个空间
    	cout << " in return_value5 ,  address and value:"<< &p <<" "<< p << endl;
     
    	return p;
    }
     
    /*		如果真要返回局部变量的引用和指针 ,请用static		*/
     
    char *return_value6()
    {
    	static char p[] = "hello world";
    	cout << " in return_value6 , static_pointer's address and value:"<< &p <<" "<< p << endl;
     
    	return p;
    }
    
    
    #include <iostream>
    #include "fun_stdy.h"
    using namespace std;
     
    int main(int argc, char **argv){
    	int *p ,*q;
    	char *pchar;
     
    	cout << " in main ,return_value0() :" << return_value0()<< endl<< endl;
     
    	p = return_value1();
    	cout << " in main ,return_value1() :" << p<< "	" << *p << endl<< endl;
     
    	p = return_value2();
    	cout << " in main ,return_value2() :" << p<< "	" << *p << endl<< endl;
     
    	q = p;
    	cout << " before return_value3 , q: " << q << "	"  << *q <<endl<< endl;
    	p = return_value3(q);
    	cout << " in main ,return_value3() :" << p<< "	" << *p << endl<< endl;
    	cout << " after return_value3 , q: " << q << "	"  << *q <<endl<< endl;
     
    	pchar = return_value4();
    	cout << " in main ,return_value3() :" << pchar<< "	" << *pchar << endl<< endl;
     
     
    	pchar = return_value5();
    	cout << " in main ,return_value5() :" << pchar<< "	" << *pchar << endl<< endl;
     
     
    	pchar = return_value6();
    	cout << " in main ,return_value6() :" << pchar<< "	" << *pchar << endl<< endl;
     
    	system("pause");
    	return 0;
    }
    
    #include <stdio.h> 
    char *returnStr() 
    { 
        char *p="hello world!"; 
        return p; 
    } 
    int main() 
    { 
        char *str; 
        str=returnStr(); 
        printf("%s\n", str); 
        return 0; 
    }
    
    这个没有任何问题,因为"hello world!"是一个字符串常量,存放在只读数据段,
    把该字符串常量存放的只读数据段的首地址赋值给了指针,所以returnStr函数退出时,
    该该字符串常量所在内存不会被回收,故能够通过指针顺利无误的访问。
    #include <stdio.h> 
    char *returnStr() 
    { 
        char p[]="hello world!"; 
        return p; 
    } 
    int main() 
    { 
        char *str; 
        str=returnStr(); 
        printf("%s\n", str); 
        return 0; 
    } 
    
    "hello world!"是局部变量存放在栈中。当returnStr函数退出时,栈要清空,
    局部变量的内存也被清空了,所以这时的函数返回的是一个已被释放的内存地址,
    所以有可能打印出来的是乱码。 
    int func()
    {
          int a;
          ....
          return a;    //允许
    }                   
     
    int * func()
    {
          int a;
          ....
          return &a;    //无意义,不应该这样做
    } 
    
    局部变量也分局部自动变量和局部静态变量,由于a返回的是值,因此返回一个局部变量是可以的,无论自动还是静态,
    
    因为这时候返回的是这个局部变量的值,但不应该返回指向局部自动变量的指针,因为函数调用结束后该局部自动变量
    
    被抛弃,这个指针指向一个不再存在的对象,是无意义的。但可以返回指向局部静态变量的指针,因为静态变量的生存
    
    期从定义起到程序结束。
    

    如果函数的返回值非要是一个局部变量的地址,那么该局部变量一定要申明为static类型。如下:

    #include <stdio.h> 
    char *returnStr() 
    { 
        static char p[]="hello world!"; 
        return p; 
    } 
    int main() 
    { 
        char *str; 
         str=returnStr(); 
        printf("%s\n", str); 
     
        return 0; 
    } 
    

    数组是不能作为函数的返回值的,原因是编译器把数组名认为是局部变量(数组)的地址。返回一个数组一般用返回指向这个数组的指针代替,而且这个指针不能指向一个自动数组,因为函数结束后自动数组被抛弃,但可以返回一个指向静态局部数组的指针,因为静态存储期是从对象定义到程序结束的。如下:

    int* func( void )
    {
        static int a[10];
        ........
        return a;
    } 
    

    返回指向堆内存的指针是可以的

    
    char *GetMemory3(int num)
    {
    char *p = (char *)malloc(sizeof(char) * num);
    return p;
    }
    void Test3(void)
    {
    char *str = NULL;
    str = GetMemory3(100);
    strcpy(str, "hello");
    cout<< str << endl;
    free(str);
    

    程序在运行的时候用 malloc 申请任意多少的内存,程序员自己负责在何时用 free释放内存。动态内存的生存期由程序员自己决定,使用非常灵活。

    展开全文
  • 局部变量作为返回值

    2019-04-09 22:54:52
    一般来说,函数是可以返回局部变量的,局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,...准确的来说,函数不能返回指向栈内存的指针(注意这里指的...
  • 局部变量作为返回值问题

    千次阅读 2014-04-23 18:10:57
    函数返回局部变量,是返回局部变量的值。但指针(或地址)是一种特殊的值,所以返回局部指针变量需要特别注意。正确情况下,作为函数返回值的局部指针,其所指向对象的作用域应该是调用者作用域、全局或静态常量区;...
  • 注意下面的代码,本意是想返回一个字符串, 但当它返回调用者的时候, 返回串却是垃圾信息。...redbuf为自动变量*/ sprintf(retbuf, "%d", n); return retbuf; /* 错!自动变量此时将销毁*/ }一种
  • 所以这种方式的变量不能作为返回值的; 另一中方式就是: A *a = new A(5,5); 这是对象是个指针,他的内存释放在堆上的; 它是可以作为返回值的;因为只是一个指针的赋予; 这种方式就是C#里用的 A a = ne
  • 一般的来说,函数是可以返回局部变量的。...准确的来说,函数不能通过返回指向栈内存的指针(注意这里指的是栈,返回指向堆内存的指针是可以的)。 下面以函数返回局部变量的指针举几个典型的例子来说明: 01...
  •  函数的局部变量用作返回值时,会生成一个局部变量的拷贝用作返回值,之后局部变量会被系统回收,函数不能返回局部变量的地址,因为如果返回局部变量的地址,系统回收后,指针指向的内容就无意义了,但是对于静态...
  • 局部变量返回值

    千次阅读 2014-06-26 12:35:19
    发现自己对返回局部变量值的理解有些误区,网上查了下...当返回值局部变量时,实际上返回的是局部变量的拷贝。 当返回值局部变量指针时,返回的是指针的拷贝,由于变量值已经释放,指针指向的值是无效的值。 当
  • 然后可以知道当在一个被调用的函数中声明一个局部指针变量,并让其作为这个函数的返回值,这个时候gcc编译会通过,但是运行时就会崩溃,原因就是使用了野指针,而这个野指针的产生原因就是因为局部变量指针返回的...
  • 函数的调用以及完成调用的过程是函数在栈内存中入栈和出栈的过程,当函数被调用时,函数入栈,当函数调用完成之后,系统负责把函数占用栈内存自动释放,所以存在栈中的局部变量的占用的内存得到释放,如果此时把当前...
  • 一般的来说,函数是可以返回局部变量的,但是要注意几种情况。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,...准确的来说,函数不能通过返回指...
  • C++函数返回值局部变量

    千次阅读 2017-11-30 21:45:28
    C++函数的返回值局部变量时,该返回值可能是值类型、指针类型和引用类型。 以自定义类型MyStruct为例: struct MyStruct { int x; int y; }; 1 返回值是自定义结构的值类型 定义一个返回值为MyStruct的函数...
  • 一般的来说,函数是可以返回局部变量的。 局部变量的作用域只在函数内部,在函数返回后,局部变量的内存已经释放了。因此,如果函数返回的是局部变量的值,不...准确的来说,函数不能通过返回指向栈内存的指针(注意...
  •   首先需要明白一件事情,临时变量,在函数调用过程中是被压到程序进程的栈中的,当函数退出时,临时变量出栈,即临时变量已经被销毁,临时变量占用的内存空间没有被清空,但是已经可以被分配给其他变量了,所以有...
  • 请教大神如下问题:根据C++的内存管理可以知道,在函数里面创建的对象是作为局部变量的,那么这个对象就会在 函数结束的时候被回收。但是如果将这个对象作为返回值返回出去呢?一样会被回收吗?
  • 为什么函数能够返回 静态变量的地址而不能返回局部自动变量的地址,到底什么样的对象能够返回其地址,而什么样的对象不能够返回其地址?静态变量局部自动变量的主要区别是什 么?    要想明白这些就需要
  • 期望得到函数c里的arr作为函数A的返回值,但是因为异步的原因,会先执行return语句,返回undefined ``` var arr=[]; let A = ()=>{ //逻辑处理 B(function(){ C(function(){ let a = 10; arr...
  • break: 结束当前所在的循环     continue:结束本次循环,继续下次循环    return: 结束当前函数      函数:   就是把一段完成独立功能的代码打包起来 ... 无参无返回值的函数:  语法:
  • 写了一个单链表,然后遇到一道题目 ...思索半天,原来是因为把函数内部的变量作为返回值而出现了问题 解决:把要做返回值的对象,改成函数调用时需要传进来的参数,返回值不要了,写成void,完美。 ...
  • 局部变量:只有方法当中才可以使用,出了方法就不能再用 成员变量:整个类全都可以通用。 3.默认值不一样【重点】 局部变量:没有默认值,如果要想使用,必须手动进行赋值 成员变量:如果没有赋值,会有默认值,规则和数...
  • 引用作为返回值

    2019-09-06 15:47:15
    不能返回局部变量的引用。主要原因是局部变量会在函数返回后被销毁,因此被返回的引用就成为了"无所指"的引用,程序会进入未知状态。 不能返回函数内部new分配的内存的引用。虽然不存在局部变量的被动销毁问题,可...
  • 临时变量作函数的返回值 我觉的要说清楚首先要从函数返回的临时变量的生命周期说起: 函数返回的临时变量是放在堆栈上的,所以返回来后如果你没有调用其他的函数,那么这个临时变量在依然保存在堆栈中,...
  • c++中将局部变量的引用作为返回

    千次阅读 2018-11-05 18:57:21
    c++中可以将引用作为返回值,比如下面这个函数 int &amp;c() { int a = 2; cout &lt;&lt; "a的地址为:" &lt;&lt; &amp;a &lt;&lt; endl; return a; } 局部变量a的...
  • /* * @Date: 2019-3-12 * @Author: tracycw ... 为什么不能返回局部指针变量,却可以返回局部变量 函数的局部变量用作返回值时,会生成一个局部变量的拷贝用作返回值,之后局部变量会被系统回收, ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 156,767
精华内容 62,706
关键字:

局部变量不能作为返回值