匿名对象的特性和使用场景你知道吗?

目录

一、匿名对象的概念

二、单参数和多参数构造场景的匿名对象

①只有一个参数的构造函数

②多个参数的构造函数

三、使用匿名对象作为函数的参数的缺省值

四、只为调用类中的一个函数时

五、匿名对象的特性

1、匿名对象的生命周期只有一行

2、匿名对象具有常性

3、当匿名对象被引用时,匿名对象的生命周期会变长


一、匿名对象的概念

匿名对象:

没有对象名,也不需要对象名,直接使用类名创建对象,如:

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int a = 1, int b = 7)
	{
		_a = a;
		_b = b;
	}
	~Date()
	{
		cout << "析构~Date()" << endl;
	}
private:
	int _a;
	int _b;
};
int main()
{
	Date();//匿名对象
	return 0;
}

二、单参数和多参数构造场景的匿名对象

对于单参数的构造函数,C++支持使用等号(=)来初始化刚创建的对象

①只有一个参数的构造函数

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year )
	{
		_year = year;
	}
	~Date()
	{
		cout << "析构~Date()" << endl;
	}
private:
	int _year;
};
int main()
{   //编译时,实际变为了 Date d = Date(2023)
	Date d = 2023;//这一步发生了隐式类型转换
	return 0;
}

使用等号(=)创建匿名对象时,会发生隐式类型转换,先通过构造函数生成一个匿名对象(临时对象),然后通过拷贝构造将该对象的值赋给刚创建的对象d

但是编译器认为这样太慢,所以直接就对该行进行了优化,从而只调用了构造函数

②多个参数的构造函数

这时可以使用缺省参数也能实现使用等号(=)来初始化刚创建的对象

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year,int month=5,int day=10 )
	{
		_year = year;
		_month = month;
		_day = day;
		
	}
	~Date()
	{
		cout << "析构~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{   //编译时,实际变为了 Date d = Date(2023)
	Date d = 2023;//这一步发生了隐式类型转换
	return 0;
}

通过调试发现,多参数也可以使用等号(=)初始化刚创建的对象

三、使用匿名对象作为函数的参数的缺省值

该使用场景在函数模板是比较常见的,当我们不确定参数的类型时可以使用匿名对象作为缺省值来给该参数指定一个默认的值,如:

vector(size_t n, const T& val = T())//vector构造函数

{}
//T()表示匿名对象

在STL中就用到了匿名对象来定义vector的构造函数 

四、只为调用类中的一个函数时

当我们只想调用类中的一个函数时,发现如果没有类的实例化就无法调用,这时就必须创建一个类对象才能调用,这样是不是就很糟糕呢,因为实例化一个对象就会申请空间,占用了多余的内存空间,这时我们就可以使用匿名对象来调用,如:

class Solution {
public:
int Sum_Solution(int n) {
//...
return n;
}
};

int main()
{
   // 匿名对象在这样场景下就很好用
  Solution().Sum_Solution(10);
   return 0;
}

这时使用匿名对象就不会占用多余的空间,因为匿名对象的声明周期只有一行,改行结束就会销毁

五、匿名对象的特性

1、匿名对象的生命周期只有一行

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year,int month=5,int day=10 )
	{
		_year = year;
		_month = month;
		_day = day;
		
	}
	~Date()
	{
		cout << _year << '-' << _month << '-' << _day << endl;
		cout << "析构~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{  
	Date(2023);//匿名对象
	Date d(2023, 5, 9);
	return 0;
}

通过结果我们可以发现,匿名对象的生命周期只有一行,因为对象的销毁顺序是 先创建的后销毁,后创建的先销毁。显然这里先销毁的匿名对象,而匿名对象又是先创建的,所以可以说明匿名对象的生命周期只有这一行

2、匿名对象具有常性

当我们这样引用时,可以发现是报错的

Date& d = Date(2023);//属于权限被放大的错误

当我们加上const修饰对象d时:

const Date& d = Date(2023);

 原因:匿名对象作为一个临时变量具有常性,当我们引用时不加const修饰就会发生权限被放大的问题,所以发生报错,权限可以被缩小和平移但不能被放大

3、当匿名对象被引用时,匿名对象的生命周期会变长

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year,int month=5,int day=10 )
	{
		_year = year;
		_month = month;
		_day = day;
		
	}
	~Date()
	{
		cout << _year << '-' << _month << '-' << _day << endl;
		cout << "析构~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{  
	const Date& d = Date(2023);//引用匿名对象
	Date d2(2023, 5, 9);
	return 0;
}

结果:

 通过结果可以发现,先销毁的是后创建的对象d2后销毁的是先创建的对象d(匿名对象的引用)

看到这大家一定会有疑惑,匿名对象的生命周期不是只有一行吗,为什么能被引用,且在后面销毁呢?

原因:匿名对象和引用它的对象的生命周期绑定在了一起,这时匿名对象的生命周期就变长了,引用它的对象的生命周期是多长,该匿名对象此时的生命周期就为多长。就像一个变量引用临时变量一样,临时变量的生命周期也变长了。

#include<iostream>
using namespace std;
class Date
{
public:
	Date(int year,int month=5,int day=10 )
	{
		_year = year;
		_month = month;
		_day = day;
		
	}
	~Date()
	{
		cout << _year << '-' << _month << '-' << _day << endl;
		cout << "析构~Date()" << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
const Date& d3 = Date(2023,5,8);//全局对象引用
int main()
{  
	static const Date& d = Date(2023);//局部对象引用
	Date d2(2023, 5, 9);
	return 0;
}

结果:

 可以发现,匿名对象的生命周期确实和引用该匿名对象的对象的生命周期绑定了

匿名对象的知识就分享到这了,如有错误的地方还请不吝指出,谢谢了,886!!!

猜你喜欢

转载自blog.csdn.net/m0_72532428/article/details/130589385