C++学习7-变量生命周期

本文探讨了C++中变量的生命周期,强调了函数调用时传参数和返回对象值时的优化策略,如传引用减少拷贝构造和析构,以初始化方式接收返回的临时对象,以及使用右值引用避免不必要的资源浪费。
摘要由CSDN通过智能技术生成

变量生命周期

int main()
{
    Test t1(10);
    Test t2; // => 不要写成 test t2() 会变成函数的声明
    Test t3(t2);
    Test t4 = t3;//t3拷贝构造t4

    // Test t5(40);
    Test t5 = Test(40); // 生成临时对象 Test(int)
/*
Test t5 = Test(40)
等于  Test t5(40)--
是用临时对象 拷贝构造同类型的对象 临时对象不产生 直接构造对象即可
不是 :生成临时对象  拷贝构造t5  析构临时对象
*/
    cout << "-----------" << endl;


    t2 = t3;// 赋值
    t2 = Test(50); // 显式生成临时对象
//显式生成临时对象  这个临时对象是要产生的 然后给t2赋值 再析构临时对象
    t2 = 50; // 隐式生成临时对象 int -> Test(int)
//把其他类型转成类的类型 要看这个类有没有一个构造函数接收这个类型来生成临时对象

    cout << "-----------" << endl;
    return 0;
}

介绍变量生命周期,先看看下面程序中函数对象的调用情况
原本程序:

Test GetTestObject(Test t)
{
    int val = t.getData();
    Test tmp(val);
    return tmp;
}
int main()
{
    Test t1;
    Test t2;
    t2 = GetTestObject(t1);
    return 0;
}

函数调用情况:
构造t1
构造t2
t1拷贝构造临时形参对象t
构造tmp
tmp拷贝构造临时对象
析构tmp
析构形参对象t
临时对象赋值给t2
析构临时对象
析构t2
析构t1

优化1.函数调用传参数,如果是对象,形参按引用来接收
优化2.函数返回对象值的时候,应该返回临时对象

下面程序体现:

class Test
{
public:
    Test(int data=10):ma(data)
    {
        cout << "Test(int)" << endl;
    }
    ~Test()
    {
        cout << "~Test()" << endl;
    }
    Test(const Test &src) :ma(src.ma)
    {
        cout << "Test(const Test&)" << endl;
    }
    void operator=(const Test &src)
    {
        cout << "operator=" << endl;
        ma = src.ma;
    }
    int getData() { return ma; }
private:
    int ma;
};
Test GetTestObject(Test &t)
{
    int val = t.getData();
    return Test(val); // 生成临时对象
}
int main()
{
    Test t1;
    Test t2;
    t2 = GetTestObject(t1);
    return 0;
}

所以传值得时候传引用 可以少两个函数: 拷贝构造和析构
函数调用情况:
构造t1
构造t2
构造带整型参数的临时对象-----(因为用临时对象 拷贝构造同类型的对象 临时对象不产生 直接构造对象即可)
临时对象赋值给t2
析构临时对象
析构t2
析构t1

注意:用临时对象 拷贝构造同类型的对象的时候才优化

优化3.应该以初始化的方式接收返回值是临时对象的返回

Test GetTestObject(Test &t)
{
    int val = t.getData();
    return Test(val); // 生成临时对象
}
int main()
{
    Test t1;
    Test t2 = GetTestObject(t1);
    return 0;
}

函数调用情况:
构造t1
构造t2------刚刚是赋值 所以要产生临时对象 而现在是直接用临时对象构造同类型的对象 所以直接构造 临时对象完全不用产生
----所以应该以初始化的方式接收返回值是临时对象的返回
析构t2
析构t1

优化4.写右值引用
因为给tmp构造了10000*4的空间 将数据拷贝进来 给临时对象 又析构掉tmp
费老大劲构造出来又析构掉
对于局部的临时的对象给外部对象拷贝构造或者重载 会匹配带右值引用参数的拷贝构造和重载函数

class Test
{
public:
    Test()
    {
        mptr = new int[10000];
        cout << "Test()" << endl;
    }
    ~Test()
    {
        delete[]mptr;
        cout << "~Test()" << endl;
    }
    Test(const Test &src)
    {
        cout << "Test(const Test&)" << endl;
        /*mptr = new int[10000];
        for (int i = 0; i < 10000; ++i)
        {
            mptr[i] = src.mptr[i];
        }*/
    }
    //main栈临时对象  tmp
    Test(Test &&src) // 带右值引用参数的拷贝构造
    {
        cout << "Test(Test&&)" << endl;
        mptr = src.mptr;
        src.mptr = nullptr;
    }

    void operator=(const Test &src)
    {
        cout << "operator=" << endl;
        if (this == &src)
            return;


        delete[]mptr;


        mptr = new int[10000];
        for (int i = 0; i < 10000; ++i)
        {
            mptr[i] = src.mptr[i];
        }
    }
    void operator=(Test &&src) // 带右值引用参数的赋值函数
    {
        cout << "operator=(Test&&)" << endl;
        if (this == &src)
            return;

        delete[]mptr;

        mptr = src.mptr;
        src.mptr = nullptr;
    }
private:
    int *mptr;
};


Test GetTestObject(Test &t)
{
    Test tmp;
    return tmp;
}
int main()
{
    Test t1;
    Test t2;
    t2 = GetTestObject(t1);
    return 0;
}

右值引用中
慎用memcpy代替for

memcpy(ptr,t.ptr,4*1024)

memcpy做的是浅拷贝,如果对象里有占用外部资源,用这个就不对 for做的会调用本身的构造或者重载 但是memcpy不会

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值