日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > C# >内容正文

C#

c# out原理 ref_移植贪吃蛇——从C#到C++

發(fā)布時(shí)間:2024/8/23 C# 39 豆豆
生活随笔 收集整理的這篇文章主要介紹了 c# out原理 ref_移植贪吃蛇——从C#到C++ 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
歡迎參與討論,轉(zhuǎn)載請注明出處。

前言

  因?yàn)槟承C(jī)緣巧合,引起了我對C++的重視。一時(shí)興起,決定將兩年前用Unity寫的Snake進(jìn)行移植。經(jīng)過兩周的抽空,總算是完成了。項(xiàng)目采用現(xiàn)代C++標(biāo)準(zhǔn)編寫,采用CMake構(gòu)建,圖形庫為SDL。由于本次的重點(diǎn)不在于圖形這塊,所以沒有使用原版的素材,采用矩形代替。

  在工程實(shí)現(xiàn)上除了基本的業(yè)務(wù)外,還實(shí)現(xiàn)了C#的event以及的Unity的GameObject與Component。

  本文將從C#開發(fā)者的角度出發(fā)比較C++的不同點(diǎn),最后總結(jié)其思想。由于本人在此之前從未有C++的工程經(jīng)驗(yàn),對于許多特性在此之前也是一知半解,對于一些事物的理解若有誤還請指教。

低成本封裝

首先最引我矚目的便是C++的參數(shù)傳遞,形如這般的函數(shù):

void Init(const string& title, int width, int height);

  由于C++的引用參數(shù)string&性質(zhì),將值傳入時(shí)不會(huì)發(fā)生拷貝,而是等于直接使用原變量。可以有效降低封裝抽象的成本,加上const字段是為使得形如"123"這樣的常量區(qū)對象也能傳入。

  當(dāng)然這在C#也并不是沒有,ref便是如此。但這在C#并不會(huì)下意識(shí)去用,畢竟在C++若是不用指針或引用作為參數(shù)的話可是會(huì)直接拷貝新對象的,而在C#直接使用也不會(huì)造成很大的負(fù)擔(dān)(值類型直接拷貝,引用類型用指針)。

  其次便是C++的內(nèi)聯(lián)函數(shù)了,作為函數(shù)宏的替代品之一。可以在編譯時(shí)將函數(shù)展開為具體的內(nèi)容,節(jié)省了一次函數(shù)調(diào)用的消耗。但內(nèi)聯(lián)函數(shù)需寫在頭文件中,若是關(guān)聯(lián)項(xiàng)多,修改后便會(huì)增加編譯時(shí)長。且展開量過大也會(huì)增大代碼量,增加編譯時(shí)長。但不失為一個(gè)降低封裝成本的手段。

明確的內(nèi)存

其次與C#最大的不同便是對象的創(chuàng)建了,C++有著以下兩種形式:

A a = A(); A* a = new A();

了解C++的自然曉得,前者在當(dāng)前內(nèi)存域下申請,后者在堆申請。而在C#則隱去了這個(gè)細(xì)節(jié),而是設(shè)立固定的規(guī)則:

  • 引用對象使用指針,原則上在堆申請,若對象的生命周期存在于申請的函數(shù)里,則在棧申請——是為逃逸分析。
  • 值對象在當(dāng)前內(nèi)存域下申請,且由于不是指針,變量傳遞會(huì)產(chǎn)生拷貝。除非使用ref、in、out等參數(shù)關(guān)鍵字。

  而C++的內(nèi)存申請機(jī)制則帶來了明確感,如在函數(shù)里申請生命周期只存在函數(shù)里的對象,需要明確的使用A a = A();方式。且在構(gòu)建類的時(shí)候,對于那些不使用A* a = new A();創(chuàng)建方式的成員變量,其內(nèi)存占用是明確的,在類對象申請內(nèi)存的時(shí)候會(huì)一并申請,即這些成員變量在內(nèi)存布局上可能是連續(xù)的。從這點(diǎn)來說可比C#要牛逼多了。

相似的容器

  在容器方面,C++與C#大體看起來是相似的,當(dāng)然在API的爽度而言還是C#更勝一籌(C++17拉近了不少)。但實(shí)際上還是存在一些細(xì)節(jié)上的不同,就比如我們常用的Key-Value容器:C++的std::map與C#的Dictionary在實(shí)現(xiàn)乃至功能上就不一樣。實(shí)際上std::map對應(yīng)C#的應(yīng)該是SortedDictionary:它們都是基于紅黑樹實(shí)現(xiàn),都是有序存儲(chǔ)的表。而Dictionary則是基于哈希實(shí)現(xiàn)的,即我們俗稱的哈希表,與之對應(yīng)的是std::unordered_map。

  通過命名能看出兩種語言在這方面的傾向性:紅黑樹占用的內(nèi)存更小,但查找和刪除的時(shí)間復(fù)雜度都是O(logn),而哈希查找和刪除的時(shí)間復(fù)雜度都是O(1)。實(shí)際使用的時(shí)候感覺還是得權(quán)衡利弊,不能貪圖方便就一直用一套。std::set與HashSet這邊也是類似的對應(yīng),以此類推。

  在序列容器方面的對應(yīng)倒是工整:std::vector對應(yīng)List,都是不斷擴(kuò)容的數(shù)組容器。鏈表方面則是std::list對應(yīng)LinkedList。但std::array卻無對應(yīng)了,硬要說的話就是與C#的原生數(shù)組對應(yīng),畢竟這個(gè)容器出現(xiàn)的意義就是彌補(bǔ)與C語言兼容的原生數(shù)組。

  順帶一提,在使用std::vector時(shí)由于會(huì)出現(xiàn)擴(kuò)容復(fù)制的問題,需要考慮好成員對象的拷貝方案,乃至于內(nèi)存泄漏的問題。

智能的指針

  內(nèi)存管理是所有編程語言都無法繞開的點(diǎn),絕大多數(shù)編程語言對于堆內(nèi)存的管理都是采用垃圾回收的方式。而在C++的鴻蒙時(shí)代則與C語言一樣,需要手動(dòng)管理指向堆內(nèi)存的指針。盡管也有std::auto_ptr這樣的東西,但在功能上還不夠全面。而手動(dòng)管理內(nèi)存將難以解決對象在多處被引用時(shí)將如何安全銷毀的問題,為了實(shí)現(xiàn)這種機(jī)制也得做出不少妥協(xié)。

  所幸隨著時(shí)代的發(fā)展,現(xiàn)代C++迎來了智能指針,它基于引用計(jì)數(shù)的規(guī)則,將裸指針包裝起來,當(dāng)符合銷毀條件后便可自動(dòng)回收。智能指針有著幾種具體的類實(shí)現(xiàn),而其中最常用的是std::share_ptr,當(dāng)它持有指針時(shí)將增加計(jì)數(shù),反之同理將減少計(jì)數(shù),最終歸0銷毀。但其較之垃圾回收有個(gè)致命的缺陷:相互引用時(shí)將一直保持計(jì)數(shù),無法銷毀。為此C++引入了std::weak_ptr:它不會(huì)增加計(jì)數(shù),在計(jì)數(shù)歸0時(shí)持有指針也隨之銷毀。如此對于相互引用的情況下,分清主次,合理分配share_ptr與weak_ptr即可解決無法銷毀的問題。

  智能指針在使用上總有一種外掛的感覺,需要成體系的去使用。不如內(nèi)置的垃圾回收式語言來的方便,且寫起來還是有一定的心智負(fù)擔(dān)(相互引用),不過在性能而言較之垃圾回收更為優(yōu)越(回收對象與時(shí)機(jī)都很明確,且是被動(dòng)進(jìn)行的)。

模板與泛型

C++的模板與C#的泛型表面上用起來很是相似,實(shí)則有所不同。以下對比兩者的差異:

template<class T, int x> // C++支持模板參數(shù),可填寫整型或指針 GenericList<T> where T : Employee // C#使用System.Object不支持的方法時(shí),需進(jìn)行類型約束指定基類 // 這么騷的操作見過么? void f(int x);template <class ... Args> void Do(Args... args) {f(args ...); };

  從實(shí)際使用體驗(yàn)與兩者的命名可以看出,「模板」的本質(zhì)是參數(shù)化代碼生成,而「泛型」則是類型參數(shù)化。即泛型只是模板功能的一部分而已。模板能實(shí)現(xiàn)的其他功能,在C#則以其他方式代替了(如變長參數(shù)params)。

后記

  從以上種種便能看出C++與C#在設(shè)計(jì)哲學(xué)上的不同,C#通過約束開發(fā)者行為從而達(dá)到更穩(wěn)定健壯的結(jié)果,哪怕會(huì)失去一定的性能與靈活性,而C++則更依賴開發(fā)者自身的素質(zhì)(如C++支持多重繼承而C#僅僅支持單類+多接口繼承)。

  從個(gè)人的使用體驗(yàn)來看,現(xiàn)代C++并非不能作為業(yè)務(wù)開發(fā)語言。只是對開發(fā)者的素質(zhì)要求較之一般語言更高,從招聘成本與項(xiàng)目穩(wěn)定性而言是個(gè)問題。如此來看,除非有必要的性能敏感且需要一定封裝的核心層(如游戲引擎),否則用C + 腳本語言或者C#/Java這類可上可下的語言是個(gè)更好的選擇。

總結(jié)

以上是生活随笔為你收集整理的c# out原理 ref_移植贪吃蛇——从C#到C++的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。