类和对象(4)
1.匿名对象
- ⽤类型(实参)定义出来的对象叫做匿名对象,相⽐之前我们定义的 类型对象名(实参)定义出来的 叫有名对象。
- 匿名对象⽣命周期只在当前⼀⾏,⼀般临时定义⼀个对象当前⽤⼀下即可,就可以定义匿名对象。
- 形式:类名+括号
class A { public: A(int a = 0) :_a(a) { cout << "A(int a)" << endl; } ~A() { cout << "~A()" << endl; } private: int _a; }; class Solution { public: int Sum_Solution(int n) { //... return n; } }; int main() { //1.普通对象 A aa1;//生命周期在整个main函数作用域 A aa2(1); // A aa1();不能这么定义对象,因为编译器无法识别下面是⼀个函数声明,还是对象定义 // 例如A func();返回值是A类型的函数声明,无法区分 //但是我们可以这么定义匿名对象,匿名对象的特点不用取名字, //但是他的⽣命周期只有这⼀⾏,我们可以看到下⼀⾏他就会⾃动调⽤析构函数 //2.匿名对象 //匿名对象类似于临时对象,匿名对象是我们主动创建的,临时对象是编译器自己产生的。 A();//生命周期只在当前这一行 A(1); //匿名对象使用场景,匿名对象在这样场景下就很好用,调用Sum_Solution函数 //一般情况下 Solution s1; cout << s1.Sum_Solution(10) << endl; //有了匿名对象后 cout << Solution().Sum_Solution(10) << endl; return 0; }2.对象拷⻉时的编译器优化
- 现代编译器会为了尽可能提⾼程序的效率,在不影响正确性的情况下会尽可能减少⼀些传参和传返 回值的过程中可以省略的拷⻉。
- 如何优化C++标准并没有严格规定,各个编译器会根据情况⾃⾏处理。当前主流的相对新⼀点的编 译器对于连续⼀个表达式步骤中的连续拷⻉会进⾏合并优化,有些更新更"激进"的编译器还会进⾏ 跨⾏跨表达式的合并优化
类型转换,传参编译器做的优化
class A { public: A(int a = 0) :_a1(a) { cout << "A(int a)" << endl; } A(const A& aa) :_a1(aa._a1) { cout << "A(const A& aa)" << endl; } ~A() { cout << "~A()" << endl; } private: int _a1; }; void f1(A aa) { } int main() { //隐式类型转换:构造+拷贝构造=》优化后直接构造 A aa1 = 1; cout << endl << endl; //传值传参-》无优化 A aa2;//调用构造函数 f1(aa2);//调用拷贝构造函数 cout << endl << endl; //构造+拷贝构造=》优化后直接构造 f1(A()); cout << endl << endl; //隐式类型转换:构造+拷贝构造=》优化后直接构造 f1(1); cout << endl << endl; return 0; }A f2() { A aa; return aa;//传值返回,不会用返回对象aa直接作为表达式的返回值 //而是调用拷贝构造产生一个返回值 //但编译器优化后 //aa 这个对象不在 f2 结束时析构,而是推迟到调用者用完返回值之后才析构。 } int main() { f2(); return 0;; }A f2() { A aa; cout << &aa << endl; return aa; } int main() { f2(); //传值返回,不会用返回对象aa直接作为表达式的返回值 //而是调用拷贝构造产生一个返回值 //但编译器优化后,只会调用一次构造 //aa 这个对象不在 f2 结束时析构,而是推迟到调用者用完返回值之后才析构。 cout << endl; A aa1 = f2();//aa是aa1的一个别名,先创建aa1,编译器进行了极大的优化 cout << &aa1 << endl; cout << endl; return 0; }aa3不能和aa是同一块空间,可能A aa3;与aa3=f2()之间会做一些其他事情。
不优化:构造+构造+拷贝+赋值运算符重载==》优化后:构造+构造+赋值(不产生临时对象)
总结:传参时,尽可能不要使用传值传参,尽可能使用匿名对象或者类型转换的方式传参
A aa1(1); f1(aa1)//有名对象传参,不推荐
f1(A(1))//推荐,匿名对象传参
f1(1)//隐式类型转换传参
传值返回,接收返回值,推荐使用拷贝构造方式接收返回值
A aa2 = f2();//推荐
A aa3; aa3 = f2();//不推荐