栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C++】对象使用过程中背后调用的方法以及对象优化

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C++】对象使用过程中背后调用的方法以及对象优化

对象使用过程中背后调用的方法

C++编译器对于对象构造的优化,用临时对象生成新对象的时候,临时对象不产生了,直接构建新对象

用临时对象赋值给已存在的对象的时候,要产生临时对象,再调用operator=

构造函数完成类型转换,(构造函数强转详细可查看博客:C++:构造函数强转、参数列表)

临时对象生存周期:所在的语句

而引用就是别名,相当于给这块内存又给了个名字,所以用引用引用临时对象,临时对象的生命周期就变成引用变量的生命周期了

所以用指针指向临时变量是不安全的,而用引用引用临时对象是安全的
程序运行,对象构造顺序以及背后调用总结

  • 先全局
  • 再进入main

注意:

  • 静态局部变量,内存分配是在程序运行之前就分配好的,因为有初值的静态局部变量存储在.data区,.data区的内存是事先就分配好的;但是静态局部变量的初始化(对象的构造)是在运行到它的时候才初始化,.data区析构的时候是程序结束(main结束)的时候析构

  • new比malloc多的:new不仅分配内存,还构建对象;delete比free多的:delete不仅释放内存,释放之前先调用析构函数

  • 析构顺序:p1,p2,p4引用的变量,t3,t2,t4,t5,t1 (注意:t1,t5,t4是在.data区,构造的时候是154,析构就是451)

对象底层调用代码示例:(注释是构造顺序与底层调用的方法)

class Test
{
public:
	// 带默认值,这三种形式都可以构造:Test() Test(10) Test(10, 10)
	Test(int a = 5, int b = 5) :ma(a), mb(b) { cout << "Test(int, int)" << endl;}
	~Test() { cout << "~Test()" << endl; }
	Test(const Test &src) :ma(src.ma), mb(src.mb) 
    { 
        cout << "Test(const Test&)" << endl;
    }
	void operator=(const Test &src) 
    {
		ma = src.ma; 
		mb = src.mb; 
		cout << "operator=" << endl;
	}
private:
	int ma;
	int mb;
};

Test t1(10, 10); // 1.Test(int, int)

int main()
{
	Test t2(20, 20); // 3.Test(int, int)
	Test t3 = t2;    // 4.Test(const Test&)
	static Test t4 = Test(30, 30); // 5.Test(int, int),等价于static Test t4(30, 30);
    
	t2 = Test(40, 40);   // 6.Test(int, int) operator= ~Test()
	t2 = (Test)(50, 50); // 7.Test(int,int) operator=  ~Test(),逗号表达式(50, 50) =  (Test)50; Test(int)
	t2 = 60; //Test(int) 8.Test(int,int) operator= ~Test()
    
	Test *p1 = new Test(70, 70);   // 9. Test(int,int) 
	Test *p2 = new Test[2];        // 10. Test(int,int) Test(int,int)
	Test *p3 = &Test(80, 80);      // 11. Test(int,int)  ~Test()
	const Test &p4 = Test(90, 90); // 12. Test(int,int)、
    
	delete p1;  // 13.~Test()
	delete[]p2; // 14. ~Test() ~Test()
}

Test t5(100, 100); // 2.Test(int, int)
函数使用过程中背后调用的方法

短短的代码调用了11个函数,可以优化

三条对象优化的规则
  • 1.函数参数传递过程中,对象优先按引用传递,不要按值传递

  • 2.函数返回对象的时候,应该优先返回一个临时对象,而不要返回一个定义过的对象

  • 接收返回值是对象的函数调用的时候,优先按初始化的方式接收,不要按赋值的方式接收

    • 初始化方式:Test t2 = GetObject(t1);

    • 赋值方式:Test t2;t2 = GetObject(t1);、


    在GetObject里面怎么知道t2在哪呢?看汇编就会发现当调用GetObject函数时,除了传入t1对象的地址,还把t2对象的地址也压入函数栈帧上了,所以GetObject可以取到t2的地址,就知道临时对象要直接构造在哪块内存上了

    分析的时候还是可以按正常的对象产生的方式去分析,但是遇到“临时对象拷贝构造同类型的新对象”时,就要注意编译器会进行优化,将临时对象直接构造在新对象的地方

经过优化,完成同样的功能,刚开始要调用11个函数,现在只需要调用4个函数

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/832476.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号