最后
终极手撕架构师的学习笔记:分布式+微服务+开源框架+性能优化
private:
int ma;
};
案例一:
int main() {
test t1;
test t2(t1);
test t3 = t1;
//test(20) 显示生成临时对象,生存周期为所在的语句
test t4 = test(20);
cout << “***********************************************” << endl;
return 0;
}
可以自己猜一下打印结果。
test()
test(const test&)
test(const test&)
test()
~test()
~test()
~test()
~test()
由上述结果可以看出:
int main() {
test t1; //调用test(int)
test t2(t1); //调用test(const test&)
test t3 = t1; //调用的依旧是test(const test&)
//test(20) 显示生成临时对象,生存周期为所在的语句
test t4 = test(20); //调用的是test(int)
//这里本应该是先初始化一个临时对象,再讲临时对象拷贝给t4,
//但事实是直接为t4调用一个构造函数,将20的值传入,这是C++在 构造对象 时的优化
//这一点可以从最后的四次析构得到应证
cout << “***********************************************” << endl;
return 0;
}
案例二:
在上面的基础上加上两行:
int main() {
test t1;
test t2(t1);
test t3 = t1;
//test(20) 显示生成临时对象,生存周期为所在的语句
test t4 = test(20);
t4 = t2;
t4 = test(30);
cout << “***********************************************” << endl;
return 0;
}
可以再想想接下来的结论:
test()
test(const test&)
test(const test&)
test()
operator =
test()
operator =
~test()
~test()
~test()
~test()
~test()
t4 = t2; // 这里调用了复制构造函数
t4 = test(30); // 这里产生了临时对象
//与上面的情况有所不同的是,这里是给一个对象进行赋值,而上面是构造
//所以这里先使用构造函数构造了一个临时对象,再使用复制构造函数将临时对象复制到t4
//离开了这条语句之后,临时对象的生命周期结束,调用析构
operator =
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;
return 0;
}
现在呢,又会产生什么样的结果嘞?
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()
那么如何才能正确的掌握Redis呢?
为了让大家能够在Redis上能够加深,所以这次给大家准备了一些Redis的学习资料,还有一些大厂的面试题,包括以下这些面试题
-
并发编程面试题汇总
-
JVM面试题汇总
-
Netty常被问到的那些面试题汇总
-
Tomcat面试题整理汇总
-
Mysql面试题汇总
-
Spring源码深度解析
-
Mybatis常见面试题汇总
-
Nginx那些面试题汇总
-
Zookeeper面试题汇总
-
RabbitMQ常见面试题汇总
JVM常频面试:
Mysql面试题汇总(一)
Mysql面试题汇总(二)
Redis常见面试题汇总(300+题)
test()
test(const test&)
test()
~test()
~test()
~test()
那么如何才能正确的掌握Redis呢?
为了让大家能够在Redis上能够加深,所以这次给大家准备了一些Redis的学习资料,还有一些大厂的面试题,包括以下这些面试题
-
并发编程面试题汇总
-
JVM面试题汇总
-
Netty常被问到的那些面试题汇总
-
Tomcat面试题整理汇总
-
Mysql面试题汇总
-
Spring源码深度解析
-
Mybatis常见面试题汇总
-
Nginx那些面试题汇总
-
Zookeeper面试题汇总
-
RabbitMQ常见面试题汇总
JVM常频面试:
[外链图片转存中…(img-GHGRL2HU-1714905902256)]
Mysql面试题汇总(一)
[外链图片转存中…(img-jLW6eZZB-1714905902256)]
Mysql面试题汇总(二)
[外链图片转存中…(img-EZCCyn8v-1714905902256)]
Redis常见面试题汇总(300+题)
[外链图片转存中…(img-XoUMOYIg-1714905902256)]