lesson3-C++类和对象(下)(二)+https://developer.aliyun.com/article/1393915
匿名对象
直接看示例:
#include <iostream> using namespace std; class A { public: A() { _count++; } A(const A& a) { _count++; } static int Get_count() { return _count; } class B { public: B() { _count++; _a = 3; } private: int _a; }; private: int _A; static int _count; }; int A::_count = 0; int main() { cout << sizeof(A) << endl; //匿名对象调用成员函数 cout << A().Get_count() << endl; return 0; }
匿名对象就是没有名字的对象,生命周期只在本行。语法就是类名加括号表示匿名对象。
拷贝对象时的一些编译器优化
class Date { public: Date(int year = 2023, int month = 11, int day = 3) :_year(year) , _month(month) , _day(day) ,count(0) { _count++; count = _count; cout << "构造-" << count << endl; } Date(const Date& a) :count(0) { _count++; count = _count; cout << "拷贝构造-" << count << endl; } ~Date() { cout << "析构-" << count << endl; } Date& operator=(const Date& a) { cout << "赋值" << endl; return *this; } private: int _year; int _month; int _day; int count; static int _count; }; int Date::_count = 0; void func(Date aa) { } Date func() { Date a; return a; }
接下来我们来写测试用例:
测试用例一:
int main() { Date a; a = 1; return 0; }
首先是a构造,接着临时对象构造,临时对象赋值给a,临时对象生命周期只在本行,临时对象析构,主函数结束a析构。
int main() { //隐式类型转换,首先是1先构造一个临时对象,接着是 //临时对象拷贝构造a Date a = 1; return 0; }
所以这就是编译器的优化,将构造加拷贝构造优化为--->构造,只有在一行上编译器才会优化。
而且只有比较新的编译器才会这么去优化,老版本的编译器是不会优化的。
至于为什么不是赋值而是拷贝构造,是因为一个存在的对象给一个将要创建的对象,是拷贝构造,而一个存在的对象给一个也已经存在的对象才是赋值。
void func(Date aa) { } int main() { Date a; func(a); return 0; }
void func(Date aa) { } int main() { //2构造匿名对象,匿名对象拷贝构造aa func(Date(2)); return 0; }
一行上,构造+拷贝构造优化为--->构造
void func(Date aa) { } int main() { //隐式类型转换,3构造临时对象,临时对象拷贝构造aa func(3); return 0; }
同样被优化为只有构造。
测试用例二:
Date func() { Date aa; return aa; } int main() { Date a; a = func(); return 0; }
a构造,aa构造,接着返回值拷贝构造临时对象,aa析构,临时对象赋值给a,如果不优化,应该是这样:
- 构造-1
- 构造-2
- 拷贝构造-3
- 析构-2
- 赋值
- 析构-3
- 析构-1
Date func() { Date aa; return aa; } int main() { Date a = func(); return 0; }
这个优化更厉害了,构造,拷贝构造+拷贝构造,最后优化到只剩构造。
再次理解封装
我们用洗衣机来举例,就像我们知道洗衣机的一系列属性,将这些属性写到一个类里,这个类就是用来描述洗衣机属性的,但他是洗衣机吗?不是,用这些属性实例化出来的对象才是洗衣机,就像我们现实生活中尽管我们清楚洗衣机的属性,但是不买一个也没有办法去洗衣服。
练习题
求1+2+3+...+n_牛客题霸_牛客网 (nowcoder.com)
class Sum { public: Sum() { _i++; _sum += _i; } static int Get_sum() { return _sum; } private: static int _i; static int _sum; }; int Sum::_i = 0; int Sum::_sum = 0; class Solution { public: int Sum_Solution(int n) { Sum arr[n]; return Sum::Get_sum(); } };
#include <iostream> using namespace std; class Sub { public: Sub(int date) :_date(date) {} int GetMonth(int year,int month) const; int operator-(Sub& d); private: int _date; int _year; int _month; int _day; }; int main() { int Date1,Date2; cin >> Date1 >> Date2; int temp; if(Date1 > Date2) { temp = Date1; Date1 = Date2; Date2 = temp; } Sub d1(Date1); Sub d2(Date2); cout << (d1-d2) << endl; return 0; } // 64 位输出请用 printf("%lld") int Sub::operator-(Sub& d) { _year = _date/10000; _month = _date/100%100; _day = _date%100; d._year = d._date/10000; d._month = d._date/100%100; d._day = d._date%100; int month = 1; int day = 1; int total = 0; if(_year == d._year) { if(_month == d._month) { return abs(_day-d._day+1); } else { int month = 1; int total_1 = 0; while(month < _month) { total_1 += GetMonth(_year,month); } total_1 += _day; month = 1; int total_2 = 0; while(month < d._month) { total_2 += GetMonth(_year,d._month); } total_2 += d._day; return abs(total_1 - total_2 + 1); } } else { int month = 1; int total_1 = 0; while(month < _month) { total_1 += GetMonth(_year,month); month++; } total_1 += _day; total_1 = 365 - total_1; if(_month>2 && _year%4==0 && _year%100!=0 || _year%400==0) { total_1--; } month = 1; int total_2 = 0; while(month < d._month) { total_2 += GetMonth(_year,month); month++; } total_2 += d._day; total = total_1 + total_2; if(d._year - _year > 1) { for(int i=_year+1; i<d._year; i++) { if(_year%4==0 && _year%100!=0 || _year%400==0) { total++; } } total += 365 * (d._year-1); } } return total + 1; } int Sub::GetMonth(int year,int month) const { int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; if(month == 2 && (_year%4==0 && _year%100!=0 || _year%400==0)) { return 29; } return month_day[month]; }
#include <iostream> using namespace std; int main() { int year; int n; int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; while(scanf("%d %d",&year,&n) != EOF) { int month = 1; int day = 1; while(n > month_day[month]) { n -= month_day[month]; month++; } if(month > 2 && (year%4 ==0 && year%100 != 0 || year%400 == 0)) { n--; if(n == 0) { month--; n = 29; } } day = n; printf("%d-%02d-%02d\n",year,month,day); } } // 64 位输出请用 printf("%lld")
#include <iostream> using namespace std; int main() { int n; cin >> n; int year,month,day,Add_Day; int month_day[13] = {0,31,28,31,30,31,30,31,31,30,31,30,31}; while(n--) { cin >> year >> month >> day >> Add_Day; int count = 0; while(count < Add_Day) { count++; day++; int num = month_day[month]; if(month == 2 && (year%4 == 0 && year%100 != 0 || year % 400 == 0)) { num++; } if(day > num) { day = 1; month++; } if(month == 13) { month = 1; year++; } } printf("%d-%02d-%02d\n",year,month,day); } } // 64 位输出请用 printf("%lld")