【C++游记】类和对象下——构造函数还有你不知道的细节、静态成员、友元函数、编译器如何优化

【C++游记】类和对象下——构造函数还有你不知道的细节、静态成员、友元函数、编译器如何优化

 

枫の个人主页

你不能改变过去,但你可以改变未来

算法/C++/数据结构/C

Hello,这里是小枫。C语言与数据结构和算法初阶两个板块都更新完毕,我们继续来学习C++的内容呀。C++是接近底层有比较经典的语言,因此学习起来注定枯燥无味,西游记大家都看过吧~,我希望能带着大家一起跨过九九八十一难,降伏各类难题,学会C++,我会尽我所能,以通俗易懂、幽默风趣的方式带给大家形象生动的知识,也希望大家遇到困难不退缩,遇到难题不放弃,学习师徒四人的精神!!!故此得名【C++游记】
 话不多说,让我们一起进入今天的学习吧~~~

1>>再看构造函数

        之前的构造函数还有一点点细节没说,今天咱再对它进行补充。

1.构造函数初始化还有一种方式,就是初始化列表。初始化列表以一个冒号开始,然后是一个个逗号进行分隔的数据成员列表,每个成员变量后跟一个括号中的初始值或者表达式。如_day(5),初始化天数为5。

2.每个成员变量在初始化列表中只能出现一次,也就是唯一性。初始化列表是所有成员变量定义初始化的地方。

3.有三类成员变量(引用、const、无默认构造)必须放在初始化列表进行初始化。

4.C++11支持成员变量在声明的时候给初始值,这个初始值主要是给没在初始化列表的成员变量使用的。

5.简单来说,能用初始化列表就用初始化列表进行初始化工作。

6.初始化列表按照成员变量在类中声明的顺序进行初始化,跟初始化列表顺序无关。

总结: 所有构造函数都有初始化列表。所有成员变量都要走初始化列表进行初始化。

#include<iostream> using namespace std; class D1 { public: D1(int year = 1, int month = 1, int day = 1) :_year(year) , _month(month) , _day(day) { } void print()const { cout << _year << " " << _month << " " << _day << endl; } private: int _year; int _day; int _month; }; int main() { D1 a; a.print(); return 0; }

 

结果为1 1 1 答案正确,这就是初始化列表啦~~

2>>static成员

        降伏了初始化列表,接下来继续打static静态怪吧~
1.用static修饰的成员变量叫静态成员变量,静态成员变量一定要在类外面初始化。为什么?因为之前我们说过类独属一个域,静态成员变量在静态区,所以要在类外面初始化。

2.静态成员变量为所有类对象共享,不属于任何一个具体的对象。

3.静态成员函数没有this指针。

4.静态成员函数可以访问其他的静态成员,但不能访问非静态的,因为没有this指针。

5.非静态的成员函数,可以访问任意的静态成员变量和函数。

6.访问静态成员要突破类域,也就是类似于命名空间的类名::静态成员或对象名.静态成员来访问。

7.静态成员受访问限定符限制。

8.静态成员变量不能在声明位置初始化,因为它不属于任何一个对象。
#include<iostream> using namespace std; class D1 { public: D1(int year = 1, int month = 1, int day = 1) :_year(year) , _month(month) , _day(day) { } void print()const { cout << _year << " " << _month << " " << _day << endl; } private: int _year; int _day; int _month; static int person;//需要在类外初始化 }; int D1::person = 1;//初始化记得带上类名 int main() { D1 a; a.print(); return 0; }

3>>友元函数

打完static,又出现了友元怪,小怪好多呀~师傅加把劲!
1.友元是突破类域的一种方式,友元分为:友元函数和友元类。使用方式是在函数声明或者类声明前面加friend,还要把友元的声明放到一个类中。

2.外部友元函数可以访问类的私有和保护成员,它是一个声明,并不是类的成员函数。可以理解为非常好的朋友,你对我干什么都可以。

3.友元可以在类中任意位置定义。

4.一个函数可以是多个类的友元。

5.友元类中的成员函数都可以是另一个类的友元函数。

6.友元类的关系是单向的。我的友元函数是你,意味着你可以随意用我东西,但是我不能随意用你东西。

7.偶尔方便可以使用,但它会增加耦合度,破坏封装。
#include<iostream> using namespace std; class B;//必须有前置声明,否则A都不认识B,vb从上往下执行。 class A { friend void print(const A& aa, const B& bb);//定义aa代替传进来的类变量,bb代替第二个类变量 private: int _a1 = 11; int _a2 = 22; }; class B { friend void print(const A& aa, const B& bb);//定义aa代替传进来的类变量,bb代替第二个类变量 private: int _b1 = 111; int _b2 = 222; }; void print(const A& aa, const B& bb) {//定义aa代替传进来的类变量,bb代替第二个类变量 cout << aa._a1 << endl; cout << bb._b1 << endl; } int main() { A a; B b; print(a, b); return 0; }

#include<iostream> using namespace std; class A { friend class B; private: int _a1 = 11; int _a2 = 22; }; class B { public: void print(const A& aa) {//定义aa代替传进来的类变量,因为A是B的友元,所以B可以访问A的成员变量 cout << aa._a1 << endl; cout << _b1 << endl; } private: int _b1 = 111; int _b2 = 222; }; int main() { A a; B b; b.print(a); return 0; }

4>>编译器的优化

最后的boos战,师傅加把劲!
1.编译器日新月异,在提高版本的过程中进行了一系列的优化,在不影响结果的情况下,会减少部分传参和传值的拷贝构造。

2.编译器的不同会进行不同的优化,连续的拷贝构造会合并成一个拷贝构造。

3.想看具体过程有两个办法,一是在Linux下关闭构造优化,命令为g++ test.cpp -fno-elide-constructors 二是使用较老的编译器,这时候都没有进行更新,也就没有优化的概念。

#include<iostream> using namespace std; class A { public: A(int a = 1) :_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 = 11; }; void f1(A aa) { } int main() { //匿名对象,也就是直接给A赋值,生命周期只有这一行,构造一次,函数内右构造一次还要拷贝一次,然后析构 f1(A(1));//连续的构造加拷贝构造会优化为一个构造 return 0; }

 

 5>>结语

        今日C++到这里就结束啦,如果觉得文章还不错的话,可以三连支持一下。感兴趣的宝子们欢迎持续订阅小枫,小枫在这里谢谢宝子们啦~小枫の主页还有更多生动有趣的文章,欢迎宝子们去点评鸭~C++的学习很陡,时而巨难时而巨简单,希望宝子们和小枫一起坚持下去~你们的三连就是小枫的动力,感谢支持~


 

Read more

[Git] 初识 Git 与安装入门

[Git] 初识 Git 与安装入门

告别文件噩梦:初识 Git 与安装入门 嘿,朋友!不知道你是不是也遇到过这样的情况:你在写一份重要的文档、报告,或者更常见的,一段代码时,为了安全起见,怕改错了回不去,或者想保留不同阶段的版本,于是不得不像这样保存文件: * “报告-v1.doc” * “报告-v2.doc” * “报告-最终版.doc” * “报告-最终版-最终的最终版.doc” * “报告-领导说再改改版.doc” * … 是不是看着就头大?电脑里塞满了各种名字相似的文件,时间一长,你根本分不清“最终版”和“最终的最终版”到底差在哪里,想要找回某个阶段的内容更是难上加难。 文档如此,我们辛辛苦苦写出来的代码更是这样!如果代码没有版本管理,那简直是一场灾难,特别是当需要和别人协作的时候。 别怕!解决这个问题的“神器”来了——它就是版本控制系统。 什么是版本控制系统? 想象一下,版本控制系统就像一个超级详细的“文件时光机”或者“改动日志本”

By Ne0inhk
copilot学生认证2026-github copilot学生认证(手把手教会)

copilot学生认证2026-github copilot学生认证(手把手教会)

1.前言 博主在24年的时候发过一篇copilot认证成功的帖子,当时也是领到了一年的pro 文章链接:github copilot学生认证(手把手一小时成功)-ZEEKLOG博客 如今26年了,copilot的申请增加了一年的时间,博主也进入了研究生生涯,前段时间也是再次进行了申请,现在已经用上了,Pro 版直接解锁无限制基础功能 + 海量高级模型,我的感受是:真香!:   既然官方的申请有变化,咱们教程也得与时俱进,下面就开始手把手教大家如何进行申请copilot学生会员。 2.完善 GitHub 账号基础配置 在Emails里面加入你对应学校的教育邮箱(以edu.cn结尾),打开教育邮箱点击GitHub发送的验证邮件链接,即可完成邮箱认证 3.Github学生认证 完成上述步骤后,打开学生认证申请链接,依旧还是在设置里面,这里也可以用手机操作,因为上传证明材料用手机拍照更方便: 选择身份为学生,下滑填写学校信息,输入学校的英文,最后选择自己的学校教育邮箱,点击continue(还得分享位置) 接下来就是上传证明材料: * 可以使用手机摄像头拍摄,证件

By Ne0inhk

git如何修改密码

1. HTTPS 方式(用户名+密码) 如果您之前用 HTTPS 地址克隆仓库(如 https://github.com/用户名/仓库名.git),密码通常保存在系统凭据中。修改密码需更新凭据: Windows(凭据管理器) 1. 打开 控制面板 → 凭据管理器 → Windows 凭据。 2. 找到对应的 Git 凭据(如 git:https://github.com),编辑或删除后重新输入密码。 macOS(钥匙串访问) 1. 打开 钥匙串访问,搜索 github.com或相关地址。 2. 修改或删除原有凭据,下次 Git 操作会提示输入新密码。 命令行清除缓存(所有系统)

By Ne0inhk

WuliArt Qwen-Image Turbo极速文生图:5分钟搞定高清AI绘画

WuliArt Qwen-Image Turbo极速文生图:5分钟搞定高清AI绘画 1. 为什么你需要一个“真能用”的本地文生图工具? 你是不是也经历过这些时刻: * 在线AI绘画平台排队半小时,生成一张图要等两分钟,还经常卡在“渲染中”; * 下载了几个开源模型,结果发现显存爆了、黑图频出、提示词不认中文、生成效果像蒙了一层雾; * 想试试赛博朋克风格,输入“霓虹雨夜街道”,出来的却是模糊的色块和扭曲的建筑轮廓; * 明明有RTX 4090,却因为模型没优化,只能开半精度跑得比笔记本还慢。 这些问题,不是你的错——而是大多数开源文生图方案,压根没为真实个人GPU环境做过工程打磨。 而今天要聊的这个镜像: WuliArt Qwen-Image Turbo,就是专治这些“水土不服”的本地化解药。它不堆参数、不讲概念,只做一件事:让你的4090真正跑起来,5分钟内从零开始,稳定输出1024×1024高清图。 它不是另一个“又一个SDXL复刻”,而是基于阿里通义千问最新多模态底座Qwen-Image-2512,再叠上Wuli-Art团队实测验证过的Turbo LoRA微

By Ne0inhk