ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2020-03-27 13:51:28  阅读:190  来源: 互联网

标签:函数 对象 C++ t1 Test 地址 fun 返回值


原文链接:https://www.cnblogs.com/yanhai307/p/10935665.html

 

参考链接:

https://www.cnblogs.com/mini-coconut/p/8542560.html

 https://www.cnblogs.com/ysherlock/p/7822287.html

问题描述

在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\n", name, this);
    }

    Test(const Test &obj)
    {
        this->name = obj.name;
        printf("%s: 执行了拷贝构造函数,我的地址是 %p,拷贝来自%s %p\n",
               name.c_str(), this, obj.name.c_str(), &obj);
    }

    ~Test()
    {
        printf("%s: 执行了析构函数, 我的地址是 %p\n", name.c_str(), this);
    }

public:
    string name;
};

Test fun()
{
    Test t("我是在fun函数中创建的");
    printf("in fun: %p\n", &t);
    return t;
}

void test1()
{
    // 这里t1对象就是fun函数里面创建的?
    cout << "fun start.." << endl;
    Test t1 = fun();
    cout << "fun end.." << endl;
    t1.name = "我是在test函数中被创建的";
    printf("我是在test函数中被创建的对象,我的地址是: %p\n", &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函数中仍然有效

标签:函数,对象,C++,t1,Test,地址,fun,返回值
来源: https://www.cnblogs.com/lh03061238/p/12580907.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有