C++编程经验(8):对象优化,试试

总结

至此,文章终于到了尾声。总结一下,我们谈论了简历制作过程中需要注意的以下三个部分,并分别给出了一些建议:

  1. 技术能力:先写岗位所需能力,再写加分能力,不要写无关能力;
  2. 项目经历:只写明星项目,描述遵循 STAR 法则;
  3. 简历印象:简历遵循三大原则:清晰,简短,必要,要有的放矢,不要海投;

以及最后为大家准备的福利时间:简历模板+Java面试题+热门技术系列教程视频

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

现在呢,又会产生什么样的结果嘞?

test()

test(const test&)

test(const test&)

test()

operator =

test()

operator =

~test()

test()

operator =

~test()

test()

operator =

~test()


~test()

~test()

~test()

~test()

t4 = (test)30; //强制类型转换

//编译器会去查看类有没有对应的构造函数

//如果有,则生成一个临时对象,跟上面那结尾那个一样

t4 = 40;

//这个也几乎一样道理,不过上面的是显示类型转换,下面这个是隐式类型转换


operator =

~test()

test()

operator =

~test()


案例四:

在上面的基础上继续添加:

int main() {

test t1;

test t2(t1);

test t3 = t1;

//test(20) 显示生成临时对象,生存周期为所在的语句

test t4 = test(20);

t4 = t2;

t4 = test(30);

t4 = (test)30;

t4 = 40;

cout << “***********************************************” << endl;

//test* p = &test(40); //&要求一个左值

const test& pp = test(50); //非常量引用的对象必须是一个左值

cout << “***********************************************” << endl;

return 0;

}

好的,引用要求一个左值,让我们再来看一下结果:


test()


~test();

可以看到,引用对象调用了一个临时对象,出了作用域之后并不被析构掉,也即是说可以用。

但是函数结束之后也是要挂掉的。

这里是编译器审查的比较严格。


此外,再讲两个构造的调用时机:

1、全局对象的构造会在函数刚开始运行的时候。

2、静态对象在程序运行的时候会分配空间,但是在函数运行到的时候才会构造。

3、它们都在函数结束的时候析构。


接下来我们看函数调用中的对象优化。


案例五:

在上面的基础上,我们在类外再加这么一个函数:

test* GetObject(test t) {

int val = t.getdata();

test temp(val);

return &temp;

}

这里是不能这么写的,因为 temp(val) 是一个栈内临时对象,在函数结束的时候就会被析构的,如果编译不过就算了,我的VS编译过了,于是卡死了,果然没有让我失望哈。


案例六:

一波微调

test GetObject(test t) {

//不能返回局部或临时对象的指针或引用

int val = t.getdata();

test temp(val);

return temp;

}

//第一个main,做参照

int main() {

test t1;

test t2;

cout << “***********************************************” << endl;

return 0;

}

//第二次运行的main

int main() {

test t1;

test t2;

t2 = GetObject(t1);

cout << “***********************************************” << endl;

return 0;

}

产生结果:

//第一次运行的main

test()

test()


~test()

~test()

//第二次运行的main

test()

test()

test(const test&)

test()

test(const test&)

~test()

~test()

operator =

~test()


~test()

~test()

差距好大。。

记住这里,一会儿要回来

那么,对比一下,结果就是:

t2 = GetObject(t1);

产生:

test(const test&)

test()

test(const test&)

~test()

~test()

operator =

~test()

这之间有什么离奇曲折的故事呢?

首先,t1 作为实参传递给形参,怎么传递的?复制构造函数嘛。

为什么这么说呢,咱凡事讲证据。

void GetObject(test t) {

int val = t.getdata();

cout << “***********************************************” << endl;

/*test temp(val);

return temp;*/

//return NULL;

}

int main() {

test t1;

test t2;

GetObject(t1);

cout << “***********************************************” << endl;

return 0;

}

我把那底下的都注释了,返回值也免了,于是得出这么一个结果:

test() //t1

test() //t2

test(const test&) //构造形参


~test() //说明是离开了函数作用域才被析构掉的


~test()

~test()

可以说明这个传参的过程只执行了一次复制构造函数。

那么,对比上面那次,剩下的这段又是怎么肥四呢?:

test()

test(const test&)

~test()

~test()

operator =

再修改,给函数一个返回值看看:

test GetObject(test t) {

int val = t.getdata();

cout << “-----------------------------------------------” << endl;

/*test temp(val);

return temp;*/

return NULL;

}

运行结果:

test()

test()

test(const test&)


test()

~test()

~test()


~test()

~test()

去掉前面的影响,可以看到返回值对函数的影响是:产生了一个构造函数,并产生了一个析构函数。

为了探究这个这个析构函数是在哪里产生的,我给了main函数接收函数返回值的权利(其实用脚指头想都知道是在main里面析构的),不过用脚指头想不到的是,在 main 的什么部位析构,是像 t1、t2 一样在函数结束之后吗?

int main() {

test t1;

test t2;

t2 = GetObject(t1);

cout << “***********************************************” << endl;

return 0;

}

test()

test()

test(const test&)


test()

~test()

operator =

~test()


~test()

~test()

事实证明,这个返回值生成的对象在赋值之后便被析构。


现在,我们将封闭的代码解封,开对比下面两段代码的结果

test GetObject(test t) {

int val = t.getdata();

cout << “-----------------------------------------------” << endl;

test temp(val); //多了这行

cout << “-----------------------------------------------” << endl;

return temp;

}

VS

test GetObject(test t) {

int val = t.getdata();

cout << “-----------------------------------------------” << endl;

/*test temp(val);

return temp;*/

return NULL;

}

结果:

test() //构造t1

test() //构造t2

test(const test&) //构造形参t


test() //多了这个 构造temp(函数栈帧上的临时对象)


test(const test&) //还有这个 将temp复制给回调(main栈帧上的临时函数)

~test() //析构temp

~test() //析构形参

operator = //将回调赋值给t2

~test() //析构回调


~test() //析构t1

~test() //析构t2

VS

test()

test()

test(const test&)


test()

~test()

operator =

~test()


~test()

~test()

这样讲的还够清楚不?那不清楚也没办法了,收藏了多看几遍吧。


还没完呢,捋清楚这些,不是好玩儿,是要做优化的,真正的优化,正要开始。

首先,不觉得从上到下都在讲的有:形参、回调,是吧,不觉得很多余吗?

好,一个一个来,先解决这个形参的问题:

test GetObject(test &t) {

int val = t.getdata();

cout << “-----------------------------------------------” << endl;

test temp(val);

cout << “-----------------------------------------------” << endl;

return temp;

}

int main() {

test t1;

test t2;

t2 = GetObject(t1);

cout << “***********************************************” << endl;

return 0;

}

我也不想多废话了,直接使用传地址调用即可。

test()

test()


test()


test(const test&)

~test()

operator =

~test()


~test()

~test()

好!直接省了一个复制构造函数和一个析构。


为什么回调会这么麻烦呢?因为当函数运行完的时候,temp生命周期也到头了呀!!!

所以需要在用一个临时变量去接住它,再传出来,再赋值。

那我现在不想这么麻烦了!!!

接下来:

test GetObject(test &t) {

int val = t.getdata();

cout << “-----------------------------------------------” << endl;

//返回临时对象

return test(val); //这个临时对象并没有产生

}

int main() {

test t1;

test t2;

t2 = GetObject(t1); //你会发现,临时对象不产生了,不记得?往前翻、

//“当使用临时对象复制给一个对象时。。。”

cout << “***********************************************” << endl;

return 0;

}

test() //t1

test() //t2


test() //直接构造main函数栈帧上的临时对象

operator = //将main函数栈帧上的临时对象赋值给t2

~test() //析构该临时对象


~test()

~test()

一次优化少两个函数,爽吧!!!

虽然一次调用少的不多,但是积少成多,是很可观的。


你以为我就到此为止了?

你错了,“我是没有极限的!!!”

哈哈哈,借用一下台词。

再看:

int main() {

test t1;

test t2 = GetObject(t1);

cout << “***********************************************” << endl;

最后

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

image

image

其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣,

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

}

test() //t1

test() //t2


test() //直接构造main函数栈帧上的临时对象

operator = //将main函数栈帧上的临时对象赋值给t2

~test() //析构该临时对象


~test()

~test()

一次优化少两个函数,爽吧!!!

虽然一次调用少的不多,但是积少成多,是很可观的。


你以为我就到此为止了?

你错了,“我是没有极限的!!!”

哈哈哈,借用一下台词。

再看:

int main() {

test t1;

test t2 = GetObject(t1);

cout << “***********************************************” << endl;

最后

整理的这些资料希望对Java开发的朋友们有所参考以及少走弯路,本文的重点是你有没有收获与成长,其余的都不重要,希望读者们能谨记这一点。

[外链图片转存中…(img-MXt2iNgB-1715817640925)]

[外链图片转存中…(img-o0s3et8A-1715817640926)]

其实面试这一块早在第一个说的25大面试专题就全都有的。以上提及的这些全部的面试+学习的各种笔记资料,我这差不多来回搞了三个多月,收集整理真的很不容易,其中还有很多自己的一些知识总结。正是因为很麻烦,所以对以上这些学习复习资料感兴趣,

本文已被CODING开源项目:【一线大厂Java面试题解析+核心总结学习笔记+最新讲解视频+实战项目源码】收录

需要这份系统化的资料的朋友,可以点击这里获取

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值