目录
通过C++长时间的学习,我们已经学会了好多通过类定义对象的方法,例如:
- class A
- {
- public:
- A(int a = 0)
- :_a(a)
- {
- cout << "A(int a)构造" << endl;
- }
- A(const A& a1) {
- cout << "A(const A& a1)拷贝构造" << endl;
- }
- ~A()
- {
- cout << "~A()析构" << endl;
- }
-
- void Print() {
- cout << _a << endl;
- }
- private:
- int _a;
- };
-
-
- class Solution {
- public:
- Solution(double s= 3.14)
- :_st(s)
- {
- cout << "Solution(double s)构造" << endl;
- }
-
- int Sum_Solution(int n) {
- //...
- return n;
- }
- ~Solution()
- {
- cout << "~Solution()析构" << endl;
- }
- private:
- double _st;
- };
- int main() {
- //创建对象的方式
- A a1,a2; //方式1:
- A a3(10); //方式2:
- A a4(a1); //方式3:
- A a5 = 20; //方式4:
方式1:编译器会调用构造函数去创建对象;
方式2:在调用构造函数的同时给予实参直接赋值;
方式3:编译器会调用拷贝构造去创建对象;
方式4:这与方式3等价,且这会让编译器采用隐式类型转换。

A a6();
要特别注意上面这种创建对象方式,该种方式有歧义,会让编译器不知道该调用构造,还是拷贝构造,所以即使运行成功了,编译器也不会生成a6对象!
今天我再来介绍一种定义对象的方法,这种方法被称为匿名对象。
类名();
例:

调用结果:

解析:通过调试出的结果来看,类A,类Solution的匿名对象刚调用完构造函数就调用析构函数了 ,而之前我们创建的对象都是最后会调用析构函数,因此我们得出一个结论:匿名对象的生命周期是在当前行,执行A();调用构造函数,这行完了之后,跳转到下一行时,编译器会调用析构函数。而一般对象的生命周期是一个局部周期,局部结束才会被销毁。这就是一般对象和匿名对象最大的差别!
那么匿名对象到底有什么用呢?
其实你可以理解它是为懒人专用而研发的,~~哈哈哈
例:
一般对象调用函数时:
- A a1;
- a1.Print();
-
-
- Solution s1;
- int n=s1.Sum_Solution(25);
而匿名对象调用函数时:
- A().Print();
- int n=Solution().Sum_Solution(70);
一般对象调用函数需要先创建对象,其次才能再调用函数,需要两行;而匿名对象调用函数时一行就可以解决的,
- #include
- using namespace std;
-
-
- class A{
- public:
- A(int a = 0)
- :_a(a)
- {
- cout << "A(int a)构造" << endl;
- }
- A(const A& aa)
- :_a(aa._a)
- {
- cout << "A(const A& aa)拷贝构造" << endl;
- }
- A& operator=(const A& aa){
- cout << "A& operator=(const A& aa)重载函数" << endl;
- if (this != &aa)
- {
- _a = aa._a;
- }
- return *this;
- }
- ~A(){
- cout << "~A()析构" << endl;
- }
- private:
- int _a;
- };
-
- void f1(A aa){}
-
- A f2(){
- A aa(10);
- return aa;
- }
-
- A f3()
- { //注:F2与F3几乎等价
- return A(10); //返回匿名对象
- }
-
-
- int main() {
- A a1; //构造
- a1 = 20; //构造+拷贝构造+赋值运算符重载
- }

第一句调用构造函数创建对象,第二句则是将通过常量20创建临时类A对象(调用构造函数),然后a1拷贝复制(调用拷贝构造)临时类A对象值,总计调用:构造+拷贝构造+赋值重载函数。
- //优化场景1:以下这句与上面等价
- A a1 = 20;
优化后只调用了构造函数。
- A a2(2022);
- f1(a2);
- //以上两句共调用:构造+拷贝构造

解析:A a2(2022)是正常的调用构造函数+实参赋值创建对象,因为f1函数形参是类类型参数,这是调用构造函数的情况之一,所以总计调用:构造+拷贝构造
- //优化2:注,以下这句与上面等价
- f1(A(2022));

优化后只调用构造函数。
f2(); //构造+拷贝构造


解析:f2函数内部因为创建对象,所以调用构造函数,且返回值为类类型对象,这也是拷贝构造函数调用的情况之一,所以f2函数总计调用:构造+拷贝构造
- A ret;
- ret=f2(); //总结:构造+拷贝构造+拷贝构造

总计调用:构造+构造+拷贝构造+赋值重载函数
- //优化3:下面这句与上面两句等价
- A ret = f2();

优化后总计调用:构造+拷贝构造
A ret = f2(); //构造+拷贝构造
总计调用:构造+拷贝构造
- //优化4:极致优化
- A ret2 = f3();


优化后总计调用一次构造函数。
能一句能搞定的事情不要分开去编写,不要做中间商!中间商不仅赚不了差价,而且还会赔本!!!