
1.构造函数还有初始化另一种方式初始化列表初始化列表和构造函数体内 {} 赋值的区别初始化列表是对象成员初始化的地方当函数栈帧创建时为对象分配内存空间编译器会先执行初始化列表直接对对象进行初始化即创建对象后立即初始化。构造函数体内赋值是对象成员赋值的地方即在所有成员都完成定义和初始化之后对已经初始化后的成员进行赋值。两者的区别不是是否为对象开辟空间函数栈帧创建就已经开辟而是初始化时机 和是否能修改已经初始化的值对不同类型成员的影响1.const成员不能修改内容意味着只有在定义的地方直接初始化所以走必须初始化列表而不能 赋值2.引用成员必须定义的时候初始化不能是空引用必须初始化列表3.自定义类型作为成员变量对于没有默认构造函数的类也就是我们自己为了这个类显示写了带参数的构造函数编译器不再生成默认的无参构造那么在创建外层类对象的时候编译器就没办法自动调用这个成员变量的无参构造因为没有此时就需要在 外层类 的初始化列表中显式调用这个自定义类型的带参构造。class Time { public: // 手动写了带参构造编译器不再生成 Time() 默认构造 Time(int hour) :_hour(hour) {} private: int _hour; }; class Date { public: Date(int year, int month, int day) :_year(year), _month(month), _day(day), _t(1) // ✅必须在这里显式初始化Time成员_t调用Time(int) {} private: int _year1; int _month1; int _day; Time _t; // Time没有默认构造函数 };初始化列表会直接调用该类型的有参构造函数完成初始化。构造函数会先调用默认构造再调用赋值运算符完成赋值。函数体内赋值或初始化列表可以混着用尽量使用初始化列表而不是在构造函数体内赋值一部分原因是以上特殊的3类只能通过初始化列表进行初始化。注意1.初始化列表中成员变量初始化的顺序按照声明的顺序初始化声明的顺序是在内存中存放的数据建议声明的顺序与初始化列表中的顺序一致。2.如果类中声明了自定义类型的成员但是在初始化列表中没有显示初始化会自动调用默认构造无参来完成初始化情况1如果该自定义类型有默认构造那就自动调用其默认构造情况2如果没有默认构造无法自动初始化会报错。3.无论是否在初始化列表中显示成员初始化每个成员都要走初始化列表初始化C中对象的成员变量一定会在进入构造函数{}之前完成初始化。这个初始化的本质就是通过初始化列表的机制完成的即使没显示写初始化列表编译器也会自动生成默认的初始化列表只是初始化的值不符合预期罢了class Time { public: Time(int hour) : _hour(hour) { } private: int _hour; }; class Date { public: Date(int year, int month, int day) :_year(year), _month(month), _day(day), _t(1) { } private: int _year1; //这里给的是缺省值 // 如果初始化列表没有显示初始化 // 默认会用这个缺省值初始化 int _month1; int _day; Time _t; }; int main() { Date d1(0,0,0); return 0; }在类中直接为成员变量赋值如在private中的成员变量_year1;作用是为成员变量提供一个默认的初始化值当没有在初始化列表中显示初始化该成员变量编译器会自动使用这个默认值。2.static成员变量static修饰被当前类的所有对象共享不放在对象中存在静态区不属于对象属于类在类外面初始化static int _s_dDate::_s_d1类外初始化静态成员变量不能在声明的位置给初始化因为这个缺省值是给初始化列表用的静态成员变量不属于某个对象不走构造函数初始化列表。静态成员函数没有this指针 可以访问静态成员但不能访问非静态的静态成员在类里面声明类外面初始化也是类的成员受访问限定符的限制可突破类域访问3.友元我要访问你我得成为你的朋友friend声明可突破类访问限定符如果需要访问私有所以用友元包括友元类和友元函数友元仅仅是声明 friend func不是类的成员函数友元关系是单项的会破坏封装不建议多用4.内部类一个类定义在另一个类的内部内部类独立。跟定义在全局的类相比仅受类域和访问限定符的限制默认内部类是外部类的友元内部类主要给外部类使用5.匿名对象用类型定义出的对象之前的有名对象不仅需要类型还需要名字A aa1;//有名对象A ();//匿名对象Solution st;st.sum(4);//长期用or Solution().sum(4);//一次性生命周期仅在这一行匿名对象的生命周期只在当前一行6.对象拷贝时编译器的优化为了提高效率编译器进行优化主流是对于一个表达式中的连续拷贝进行合并优化来减少一些传参和传返回值中可以省略的拷贝A aa11构造拷贝构造编译器优化const A aa21;构造出一个临时对象直接引用无拷贝构造临时对象的产生场景类型转换传值传参需要拷贝构造一般不优化传返回值传值传参返回会产生临时对象因为aa出了作用域就销毁有时候语义上要用传值传参但是有缺点是要拷贝这时候编译器就要对此进行优化类和对象完。