• C++中函数返回值是一个对象时的问题


    问题描述

    在C++程序中,一个函数返回值是一个对象时,返回的是函数内部的局部变量本身,
    还是会产生一个中间对象(匿名对象)呢?

    经过测试,在win平台和Linux平台效果不同

    代码如下

    //
    // Created by YANHAI on 2019/5/28.
    //
    #include <iostream>
    using namespace std;
    
    class Test {
    public:
        Test(const char *name)
        {
            this->name = name;
            printf("%s: 执行了构造函数, 我的地址是 %p
    ", name, this);
        }
    
        Test(const Test &obj)
        {
            this->name = obj.name;
            printf("%s: 执行了拷贝构造函数,我的地址是 %p,拷贝来自%s %p
    ",
                   name.c_str(), this, obj.name.c_str(), &obj);
        }
    
        ~Test()
        {
            printf("%s: 执行了析构函数, 我的地址是 %p
    ", name.c_str(), this);
        }
    
    public:
        string name;
    };
    
    Test fun()
    {
        Test t("我是在fun函数中创建的");
        printf("in fun: %p
    ", &t);
        return t;
    }
    
    void test1()
    {
        // 这里t1对象就是fun函数里面创建的?
        cout << "fun start.." << endl;
        Test t1 = fun();
        cout << "fun end.." << endl;
        t1.name = "我是在test函数中被创建的";
        printf("我是在test函数中被创建的对象,我的地址是: %p
    ", &t1);
    }
    
    int main()
    {
        cout << "--------test1 start ...-----" << endl;
        test1();
        cout << "--------test1 end ...-----" << endl;
        return 0;
    }
    

    测试过程

    在win平台

    使用VS2019编译并运行

    运行结果:

    --------test1 start ...-----
    fun start..
    我是在fun函数中创建的: 执行了构造函数, 我的地址是 010FFAC4
    in fun: 010FFAC4
    我是在fun函数中创建的: 执行了拷贝构造函数,我的地址是 010FFBD4,拷贝来自我是在fun函数中创建的 010FFAC4
    我是在fun函数中创建的: 执行了析构函数, 我的地址是 010FFAC4
    fun end..
    我是在test函数中被创建的对象,我的地址是: 010FFBD4
    我是在test函数中被创建的: 执行了析构函数, 我的地址是 010FFBD4
    --------test1 end ...-----
    

    过程解释:

    1. 在fun函数中,t对象被创建,执行t对象的构造函数(t对象地址为 010FFAC4)
    2. 在fun函数执行return时,会产生一个匿名对象,会执行匿名对象的拷贝构造函数,相当于执行了 Test tmp = t; (匿名对象tmp地址为010FFBD4)
    3. fun函数执行结束,局部变量对象t被释放,执行t对象的析构函数,fun函数将匿名对象(tmp)返回(返回的是010FFBD4地址的匿名对象)
    4. 在test1函数中,t1对象被创建时 使用了fun函数的返回值,故匿名对象tmp直接变为t1对象(而不是执行拷贝构造函数给t1,就比如执行了Test t1 = Test("xx");)(t1对象的地址即为匿名对象地址 010FFBD4)
    5. test1函数执行完毕后,t1对象被释放,执行t1的析构函数

    在linux平台

    使用g++编译

    运行结果:

    --------test1 start ...-----
    fun start..
    我是在fun函数中创建的: 执行了构造函数, 我的地址是 0x7ffe5a2488c0
    in fun: 0x7ffe5a2488c0
    fun end..
    我是在test函数中被创建的对象,我的地址是: 0x7ffe5a2488c0
    我是在test函数中被创建的: 执行了析构函数, 我的地址是 0x7ffe5a2488c0
    --------test1 end ...-----
    

    过程解释:

    1. 在fun函数中,t对象被创建,执行t对象的构造函数(t对象地址为 0x7ffe5a2488c0)
    2. 在fun函数结束时,并没有产生匿名对象,而是将t对象返回(返回的是0x7ffe5a2488c0地址的对象t)
    3. 在test1函数中,t1对象被创建时 使用了fun函数的返回值,故返回对象t直接变为t1对象(而不是执行拷贝构造函数给t1,就比如执行了Test t1 = Test("xx");)(t1对象的地址即为t对象地址 0x7ffe5a2488c0)
    4. test1函数执行完毕后,t1对象被释放,执行t1的析构函数

    结论

    1. 在linux平台上,少产生了一个匿名对象,提高了执行效率
    2. 原本仅在fun函数内有效(局部变量生存周期)的t对象,由于被返回,在test1函数中仍然有效
  • 相关阅读:
    RMAN还原时注意set newname时文件名不要有空格
    注意Vietnamese_CI_AS排序规则下的特殊字符大小敏感问题
    ORA-04028: cannot generate diana for object xxx
    Linux传统Huge Pages与Transparent Huge Pages再次学习总结
    SQL Server 死锁的告警监控
    PlateSpin备份服务器时SQL Server的一些活动信息
    MS SQL xp_instance_regwrite设置注册表疑惑
    AutoAudit研究学习
    The Windows account sa does not exist and cannot be provisioned as a SQL Server system administrator
    Innotop简单介绍
  • 原文地址:https://www.cnblogs.com/yanhai307/p/10935665.html
Copyright © 2020-2023  润新知