欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

C++ 函数返回局部变量的原理 函数返回临时对象和返回临时数组(非对象)

程序员文章站 2022-03-17 14:02:40
...

函数返回局部变量的原理:

 一般说来,函数中是可以进行局部变量的返回的,不然岂不是全部要用全局变量,如果使用了全局变量,那还有必要进行返回吗?那函数就没有它存在的意义了!但是要注意了,这里所谓的局部变量的返回很有内涵,什么样的值才可以进行返回而不出错?

其实,只要遵守一句话即可:函数不能返回指向栈内存的指针!

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

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

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

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

函数返回临时对象和返回临时数组(非对象):

今天在看以前的代码的时候,看到一个函数类似如下:

                   string a=“aaa”
                   return a  

函数也能成功返回,但是我想到之前在写C语言函数的时候,返回值不能是临时变量(该变量是指向字符串),比如

#include <stdio.h>

char * fun()
{
    char a[10] = "aa";
    return a;
}

int main()
{
    char *p;
    p = fun();
    printf("%s\n",p);
    return 0;
}

函数最终打印为空。说明函数没有返回数组。但是为什么返回string临时变量可以呢?

经过搜索,查找,发现

---------------------------------------------------------------------------------------------

当函数返回字符串的时候,我们可以定义返回string和string&。

1写一个返回string引用的函数

std::string & TestStringReference()
{
    std::string loal_str = "holy shit";
    return loal_str;
}
这个函数当然是错误的,编译器会提示我们: 
返回局部变量或临时变量的地址: loal_str 

即不能返回局部变量的引用。

2写一个返回string的函数(函数返回局部变量string的时候能不能被引用?)

std::string TestStringReference()
{
    std::string strTest = "This is a test.";
    return strTest;
}
那么对于上述函数的返回值可以被引用吗? 

代码说话:

#include<iostream>
#include<string>
std::string TestStringReference()
{
    std::string strTest = "This is a test.";
    return strTest;
}

int main()
{
    std::string& strRefer = TestStringReference();
    std::cout << "strRefer:" << strRefer << std::endl;
    return 0;
}
代码 完美运行。 

实际上返回的不是局部变量,而是编译器新构造的临时对象。

3返回string的函数直接调用.c_str() 

上面说了,返回的“局部”string可以被引用的,那么返回的“局部”string直接调用.c_str()会有什么效果恩?

#include<iostream>
#include<string>
std::string TestStringC_STR()
{
    std::string strTest = "This is a test.";
    return strTest;
}

int main()
{
    const char *pc = TestStringC_STR().c_str();
    std::cout << pc << std::endl;
    return 0;
}

上面代码编译器不会报错! 
但是等等,别高兴太早,看看输出结果,为空,不是我们期望的。

关键是,我们没有将TestStringC_STR()的结果赋给一个string对象就直接获取其指针了,这时,系统并不会为string调用拷贝构造函数或是赋值函数,返回的string仍然只是一个临时对象的状态,它会在完成对pc的赋值后被销毁,这时其内部的数据也不会存在了。

解决方法:先用一个string接收函数的返回值,然后再调用c_str()方法:


#include<iostream>
#include<string>
std::string TestStringC_STR()
{
    std::string strTest = "This is a test.";
    return strTest;
}

int main()
{
    std::string str1 = TestStringC_STR();
    const char *pc = str1.c_str();
    std::cout << pc << std::endl;
    return 0;
}
参考地址:https://blog.csdn.net/wangshubo1989/article/details/50286985
相关标签: 函数返回值