C++学习:对象优化

对象优化学习笔记

对象使用过程中调用了哪些方法?

构造函数、析构函数、拷贝构造函数、赋值运算符重载函数。

#include <iostream>

using namespace std;

class Test
{
public:
    Test(int a = 5, int b = 5) : ma(a), mb(b)
    {
        cout << "Test(a, b)" << endl;
        cout << a << " " << b << endl;
    }
    ~Test()
    {
        cout << "~Test()" << endl;
    }
    Test(const Test &src) : ma(src.ma), mb(src.mb)
    {
        cout << "Test(const Test& src)" << endl;
    }
    void operator=(const Test &src)  //operator一定要拼写正确
    {
        ma = src.ma;
        mb = src.mb;
        cout << "operater= (const Test& src)" << endl;
    }
private:
    int ma;
    int mb;
};

Test t1(10, 10);

int main()
{
    Test t2(20, 20);
    Test t3 = t2;
    Test t4_ = Test(35, 35);
    static Test t4 = Test(30, 30);
    t2 = Test(40, 40);
    t2 = (Test)(50, 50);
    t2 = 60;
    Test *p1 = new Test(70, 70);
    Test *p2 = new Test[2];
    Test *p3 = &Test(80, 80);
    const Test &p4 = Test(90, 90);
    cout << "-------------------" << endl;
    delete p1;
    delete[] p2;
    return 0;
}
Test t5(100, 100);


/* 打印输出
Test(a, b)
10 10                           //Test t1(10, 10);
Test(a, b)                      
100 100                         //Test t5(100, 100);
Test(a, b)
20 20                           //Test t2(20, 20);
Test(const Test& src)           //Test t3 = t2; 定义阶段,不会调用赋值运算符重载,而是调用拷贝构造
Test(a, b)
35 35                           //Test t4_ = Test(35, 35); 编译器优化,不会生成临时对象再赋值,而是直接构造
Test(a, b)
30 30                           //static Test t4 = Test(30, 30); 同上
Test(a, b)                      
40 40                           
operater= (const Test& src)
~Test()                         //t2 = Test(40, 40); 先构造临时对象,然后调用赋值运算符重载进行赋值,赋值完成后,临时对象析构
Test(a, b)
50 5
operater= (const Test& src)
~Test()                         //t2 = (Test)(50, 50); 过程同上
Test(a, b)
60 5
operater= (const Test& src)
~Test()                         //t2 = 60;
Test(a, b)
70 70                           //Test *p1 = new Test(70, 70); 堆上分配内存,并构造对象,此时不会析构
Test(a, b)
5 5
Test(a, b)
5 5                             //Test *p2 = new Test[2]; 动态分配数组,采用默认构造函数构造了两个对象
Test(a, b)
80 80
~Test()                         //Test *p3 = &Test(80, 80); 指针指向临时对象的地址。先构造临时对象,语句完成后析构,指针变成野指针
Test(a, b)
90 90                           //const Test &p4 = Test(90, 90); 常引用,构造临时对象,语句完成后不析构 (c++11后只允许常引用引用临时对象)
-------------------
~Test()                         //析构p1指向的对象
~Test()                         
~Test()                         //析构p2动态数组上的对象
~Test()                         //析构p4引用的对象 
~Test()                         //析构t4_
~Test()                         //析构t3
~Test()                         //析构t2
~Test()                         //析构t4,t4是静态局部变量,和全局变量t1,t5存储在数据段上,最后才析构,析构顺序与构造顺序相反
~Test()                         //析构t5
~Test()                         //析构t1
*/

C++效率本身不低,关键在于开发者:减少对象使用过程中调用的方法(对象优化)。

函数调用过程中对象调用的方法太多

实例:

#include <iostream>

using namespace std;

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)
    {
        ma = src.ma;
        cout << "operator=(const Test&)" << endl;
    }
    int getData() const
    {
        return ma;
    }

private:
    int ma;
};

Test getObject(Test t)
{
    int val = t.getData();
    Test tmp(val);   // 2. 调用构造函数,构造局部对象tmp
    return tmp;      // 3. 返回tmp:/*要把tmp对象拷贝main函数栈帧上的一个临时对象(此处步骤被编译器优化掉了)*/ 析构形参t
}

int main()
{
    Test t1;  //调用带默认参数的构造函数
    Test t2;    //调用带默认参数的构造函数
    t2 = getObject(t1); /*
    1. 函数传参,调用拷贝构造函数把对象拷贝给形参
    4. 赋值运算符将main函数栈帧的临时对象赋值给t2, 然后析构临时对象
    */
    return 0;
    /*
    析构t2
    析构t1
    */
}

/*
Test(int)
Test(int)
Test(const Test&)
Test(int)
operator=(const Test&)
~Test()  //析构tmp
~Test()  //析构形参
~Test()  //析构t2
~Test()  //析构t1
*/

关闭编译器优化的输出结果:

-fno-elide-constructors # g++添加该参数,关闭编译器优化
Test(int)
Test(int)
Test(const Test&)
Test(int)
Test(const Test&)         //main函数栈临时对象拷贝
~Test()                    //tmp析构
operator=(const Test&)   //临时对象赋值给t2
~Test()   //析构临时对象
~Test()   //析构形参t(有的编译器,在main栈临时对象拷贝完成,tmp析构后,就析构了形参)
~Test() 
~Test() 

三条对象优化规则

  1. 函数参数传递过程中,对象优先按引用传递,不要按值传递(减少形参的拷贝构造和析构)

    Test getObject(Test& t)
    {
        int val = t.getData();
        Test tmp(val);  
        return tmp; 
    }
    
  2. 函数返回对象时,尽量返回临时对象,而不是先定义对象再返回。(临时对象被优化,直接再main栈上构造临时对象)

    Test getObject(Test& t)
    {
        int val = t.getData();
        // Test tmp(val);  
        // return tmp; 
        return Test(val);
    }
    
  3. 接受函数返回的对象时,直接初始化的时候接收,而不是先定义一个对象再接收。(main函数栈上的临时对象也被优化)

    Test t1; 
    // Test t2;
    // t2 = getObject(t1);
    Test t2 = getObject(t1);
    

添加带右值引用的拷贝构造和赋值运算符重载函数

Test(Test &&src) : ma(src.ma)
{
    cout << "Test(const Test&)" << endl;
}
void operator=(Test &&src)
{
    ma = src.ma;
    cout << "operator=(const Test&)" << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值