zoukankan      html  css  js  c++  java
  • 关于函数返回值的几种情况

    转自http://patmusing.blog.163.com/blog/static/13583496020113191407531/

    在一个函数的内部,return的时候返回的都是一个拷贝,不管是变量、对象还是指针都是返回拷贝,但是这个拷贝是浅拷贝。

     

    1.     如果返回一个基本类型的变量,比如:

    int a;

    a = 5;

    return a;

     

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

     

    2.     但是对于非动态分配(new/malloc)得到的指针,像1那么做就会有问题,比如在某个函数内部:

    int a[] = {1, 2};

    return a;

    那么也会返回指针a的一个拷贝,我们假定a的地址值为0x002345FC,那么这个0x2345FC是能够成功返回的。当return执行完成后,a就要被销毁,也就是0x002345FC所指向的内存被回收了。如果这时候在函数外面,去地址0x002345FC取值,那得到的结果肯定是不对的。这就是为什么不能返回局部指针的原因。返回局部变量的引用的道理和这个类似。

     

    3.     对于返回(动态分配得到的)指针的另外一种情况,比如在函数内部:

    int a = new int(5);

    return a;

    这样做是可以的。return a执行完后,a并没有被销毁(必须要用delete才能销毁a),所以这里返回的a是有效的。

     

    4.     如果不是基本数据类型,比如:

    class A

    {

    public:

                   OtherClass * ...

    };

     

    如果在某个函数内部有一个A类的局部变量,比如:

    A a;

    return a;

    这时候也会返回a的一个拷贝,如果A没有写深拷贝构造函数,就会调用缺省的拷贝构造函数(浅拷贝),这样做就会失败的;

    如果A中提供了深拷贝构造函数,则这样做就是可以的。

     

    实验代码如下:

    #include <iostream>

    using namespace std;

    int some_fun1()

    {

        int a = 5;

        return a;                   //OK

    }

     

    int* some_fun2()

    {

        int a = 5;

        int *b = &a;

        return b;                   // not OK

    }

     

    int* some_fun3()

    {

        int *c = new int(5);

        return c;                   // OK, return c执行完后并没被销毁必须要用delete才能销毁

    }

     

    class CSomething

    {

    public:

        int a;

        int b;

     

    public:

        CSomething(int a, int b)

        {

            this->a = a; 

            this->b = b;

        }

    };

     

    class CA

    {

    private:

        CSomething* sth;            // 以指针形式存在的成员变量

                                   

    public:

        CA(CSomething* sth)

        {

            this->sth = new CSomething(sth->a, sth->b);

        }

     

        // 如果不实现深拷贝,请注释这个拷贝构造函数

        CA(CA& obj)

        {

             sth = new CSomething((obj.sth)->a, (obj.sth)->b);

        }

     

        ~CA()

        {

            cout << "In the destructor of class CA..." << endl;

            if (NULL != sth) delete sth;

        }

        void Show()

        {

            cout << "(" << sth->a << ", " << sth->b << ")" << endl;

        }

        void setValue(int a, int b)

        {

            sth->a = a;

            sth->b = b;

        }

        void getSthAddress()

        {

            cout << sth << endl;

        }

    };

     

    CA some_fun4()

    {

        CSomething c(1, 2);

        CA a(&c);

        return a;                       // 如果CA没有实现深拷贝not OK如果实现深拷贝OK

    }

     

    int main(int argc, char* argv[])

    {

        int a = some_fun1();

        cout << a << endl;              // OK

     

        int *b = some_fun2();

        cout << *b << endl;             // not OK即便返回结果正确也不过是运气好而已

     

        int *c = some_fun3();           // OK, return c执行完后c并没有被销毁必须要用delete才能销毁

        cout << *c << endl;

        delete c;

     

        CA d = some_fun4();             // 如果CA没有实现深拷贝not OK如果实现深拷贝OK

        d.Show();

     

     

        return 0;

    }

  • 相关阅读:
    js识别键盘操作
    抽奖活动 算法设计
    Eureka 配置项说明
    manjaro 更新chrome报签名错误
    manjaro系统上使用asdf安装php注意事项
    Failed to load config "react-app" to extend from.
    YarnV2 install
    银河麒麟安装达梦数据库失败Unable to load native library: libnsl.so.1: cannot open shared object file: No such file or directory
    Net5中使用Swagger
    编译Windows 版本的Redis 6.x
  • 原文地址:https://www.cnblogs.com/daoxuebao/p/2376556.html
Copyright © 2011-2022 走看看