2024年Java最新C++编程经验(8):对象优化,java面试刷题

最后

终极手撕架构师的学习笔记:分布式+微服务+开源框架+性能优化

image

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

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

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常频面试:

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Mysql面试题汇总(一)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Mysql面试题汇总(二)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

Redis常见面试题汇总(300+题)

Redis高频面试笔记:基础+缓存雪崩+哨兵+集群+Reids场景设计

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

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

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)]

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

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

  • 16
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java中,可以使用 `java.util.function.Function` 接口来实现类似于 C++ 中的 `std::arg(std::complex)` 函数。 首先,我们可以定义一个 `Complex` 类表示复数,包含实部和虚部: ```java class Complex { private double real; private double imaginary; public Complex(double real, double imaginary) { this.real = real; this.imaginary = imaginary; } public double getReal() { return this.real; } public double getImaginary() { return this.imaginary; } } ``` 然后,我们可以定义一个 `arg` 函数,该函数接受一个 `Complex` 对象作为参数,并返回该复数的幅角(弧度制): ```java import java.util.function.Function; public class Main { public static void main(String[] args) { // 创建一个复数对象 Complex z = new Complex(1.0, 1.0); // 调用 arg 函数获取幅角 double arg = arg(z); // 输出结果 System.out.println(arg); } public static double arg(Complex z) { // 使用 Function 接口计算幅角 Function<Complex, Double> argFunc = (c) -> Math.atan2(c.getImaginary(), c.getReal()); // 调用 apply 方法获取结果 return argFunc.apply(z); } } ``` 在 `arg` 函数中,我们定义了一个 `Function` 对象 `argFunc`,该对象接受一个 `Complex` 对象作为参数,并使用 `Math.atan2()` 方法计算幅角。然后,我们调用 `apply()` 方法,将复数对象传递给 `argFunc`,得到幅角的结果。 注意,`Math.atan2()` 方法返回的是弧度制的幅角,与 C++ 中的 `std::arg()` 函数一致。如果需要得到角度制的幅角,可以将结果乘以 `180.0/Math.PI`。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值