網站首頁 編程語言 正文
一:背景
在C#中要說類默認給我們定義的特殊成員函數,莫過于構造函數,但在 C++ 中這樣的特殊函數高達 6 種,有必要整合一下聊一聊。
二:特殊成員函數
1. 默認構造函數
和 C# 一樣,很多書中都說,如果用戶沒有定義?構造函數,那么編譯器會給我們定義一個,參考下面的例子:
class Person { public: string name; int age; }; int main() { Person person; }
接下來觀察下匯編代碼,看下有沒有調用?默認構造函數?.
?? ?Person person;
003E32EF ?lea ? ? ? ? ecx,[person] ?
003E32F2 ?call ? ? ? ?Person::Person (03E15EBh)
對于 C# 學習者來說有點懵哈,定義了就相當于new了, 哈哈,這是因為C++默認都是值類型哈,不過這里有必要澄清一下,并不一定所有情況都會調用默認構造函數,因為C++的匯編生成由各自 編譯器 來決定,如果?編譯器?覺得沒必要調用構造函數?那它就會把這一步省掉來加速性能,那什么時候不會調呢? 參考如下代碼。
class Person { public: void show() { printf("show!"); } }; int main() { Person person; person.show(); }
接下來看下匯編代碼。
?? ?person.show();
00E73F4F ?lea ? ? ? ? ecx,[person] ?
00E73F52 ?call ? ? ? ?Person::show (0E713B6h)?
可以清楚的看到,這種情況下調用構造函數其實沒有必要,所以編譯器就干脆省略了。
2. 析構函數
在C#中析構函數?是由CLR負責管理,在C++中沒有托管這個概念,所以默認只能是結束作用域之前,自動調用析構函數釋放,參考如下圖:
3. 賦值構造函數
剛才也說到了,在 C++ 中甭管是 class 還是 struct 默認都是值類型,既然是值類型就存在stack copy
?的情況,在 C# 中也是因為重寫了?Equals
?和?GetHashCode
?來實現的值copy,接下來簡單看下代碼:
class Person { public: string name; int age; }; int main() { Person p1 = { "jack",20 }; Person p2(p1); }
再看下?Person p2(p1)
?的匯編代碼。
?? ?Person p2(p1);
000F80A2 ?lea ? ? ? ? eax,[p1] ?
000F80A5 ?push ? ? ? ?eax ?
000F80A6 ?lea ? ? ? ? ecx,[p2] ?
000F80A9 ?call ? ? ? ?Person::Person (0F15C3h)?
從匯編中可以看到調用了?Person::Person (0F15C3h)
?函數,請注意,這個不是構造函數,而是?賦值構造函數, 可以調試下去看看哦。。。 截圖如下:
值得說一下的是,C++ 默認提供的賦值構造函數是淺copy,如果要實現深 copy 的話,或者有一些自定義的邏輯,建議自己實現一下。
class Person { public: string name; int age; public: Person(string name, int age) :name(name), age(age) {} Person(const Person& p) { name = p.name; age = p.age; } }; int main() { Person p1 = { "aaaaaaaaaaaaaaaaaaaaaaaaaaa",20 }; Person p2(p1); }
4. 賦值運算符
在 C# 中值類型,?匿名類型,?Record
?都是重寫過?Equals
?及?=
?運算符,所以可以在這些類型上用?=
, 其實在 C++ 中也可以在 class 之間進行賦值,因為編譯器會幫我們重寫運算符?=
?,如何看出來呢?先看下代碼:
class Person { public: string name; int age; public: Person(string name, int age) :name(name), age(age) {} Person(const Person& p) { name = p.name; age = p.age; } }; int main() { Person p1 = { "aaaaaaaaaaaaaaaaaaaaaaaaaaa",20 }; Person p2 = { "bbbbbbbbbbbbbbbbbbbbbbbbbbb",22 }; p2 = p1; }
最后一句的?p2 = p1
?之所以能成功是因為?=
?被重寫了,參考匯編代碼。
?? ?p2 = p1;
00FD967C ?lea ? ? ? ? eax,[p1] ?
00FD967F ?push ? ? ? ?eax ?
00FD9680 ?lea ? ? ? ? ecx,[p2] ?
00FD9683 ?call ? ? ? ?Person::operator= (0FD161Dh)?
如果需要自定義,可以自己重寫。
class Person { public: string name; int age; public: Person(string name, int age) :name(name), age(age) {} Person(const Person& p) { name = p.name; age = p.age; } Person& operator = (const Person& p) { name = p.name; age = p.age; return *this; } }; int main() { Person p1 = { "aaaaaaaaaaaaaaaaaaaaaaaaaaa",20 }; Person p2 = { "bbbbbbbbbbbbbbbbbbbbbbbbbbb",22 }; p2 = p1; }
原文鏈接:https://www.cnblogs.com/huangxincheng/p/16468790.html
相關推薦
- 2023-02-10 rust引用和借用的使用小結_Rust語言
- 2022-07-27 Python?虛擬環境的價值和常用命令詳解_python
- 2022-06-23 分布式醫療掛號系統整合Gateway網關解決跨域問題_其它綜合
- 2022-12-10 C++中如何將數據保存為CSV文件_C 語言
- 2022-09-21 使用注解實現Redis緩存功能_Redis
- 2022-10-11 RabbitMQ:生產者消息確認、消息持久化、消費者消息確認、消費失敗重試機制
- 2022-07-28 Redis特殊數據類型bitmap位圖_Redis
- 2022-02-25 image-webpack-loader 報錯 Invalid regular expression
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支