亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

c/c++ 奇技淫巧(一些c語言的技巧)

 更新時間:2017年03月13日 22:49:05   投稿:mdxy-dxy  
這篇文章主要介紹了c/c++ 奇技淫巧,需要的朋友可以參考下

一. 變長數(shù)組

嚴格說來,變長數(shù)組的實現(xiàn)在c++中并不是一件麻煩的事情。Stl中的vector本身就是一個變長數(shù)組,并且有自動管理內(nèi)存的能力。
但是在c中,實現(xiàn)變長數(shù)組就稍顯麻煩。用C實現(xiàn),必然需要一個結(jié)構(gòu),結(jié)構(gòu)當中應(yīng)當有一個指針,指針分配一段內(nèi)存空間,空間大小根據(jù)需要而定,而且必須有另外一個字段記錄究竟開辟了多大多長的空間。
大致描述如下:

Struct MutableLenArray
{
  Int count;
  Char* p;
};

P = new Char[Count];

沒什么問題,但是C語言的使用者有個最大的自豪就在于對于效率、空間使用的掌控。他們會有這樣的疑問,如果count=0,那么p就沒必要了,白白占了4(64位系統(tǒng)為8)個字節(jié)的空間,簡直浪費。
那有沒有更好的方式能實現(xiàn)上面的需求,又保證空間合理呢?答案是有的,用0長度

Struct MutableLenArray 
{ 
Int count; 
Char p[0]; 
}; 

和上面的結(jié)構(gòu)使用方法一致,但是我們可以用sizeof嘗試讀取其大小,發(fā)現(xiàn)竟然只有count字段的長度4字節(jié),p沒有被分配空間。完美!

二. 宏的妙用

1. #和

“#”符號把一個符號直接轉(zhuǎn)換為字符串,例如:

#define TO_STRING(x) #x 
const char *str = TO_STRING( test ); 

str的內(nèi)容就是”test “,也就是說#會把其后的符號 直接加上雙引號。
這個特性為c++反射的實現(xiàn)提供了極大便利,可以參考博主的下一篇文章,c++反射的簡單實現(xiàn)。

##符號會連接兩個符號,從而產(chǎn)生新的符號(詞法層次),例如:

#define SIGN( x ) INT_##x 
  int SIGN( 1 ); 

宏被展開后將成為:int INT_1;
可以把##看成連字符,連字符為則為新符號的產(chǎn)生提供了方便。Google的Gtest框架就巧妙的運用了連字符來生成新的測試案例。

2. 變參宏

#define LOG( format, ... ) printf( format, __VA_ARGS__ ) 
  LOG( "%s %d", str, count ); 

VA_ARGS是系統(tǒng)預(yù)定義宏,被自動替換為參數(shù)列表。
經(jīng)常需要進行輸出格式化,重定義時,可以用到以上技巧。

3. 宏參數(shù)的prescan

prescan的定義:當一個宏參數(shù)被放進宏體時,這個宏參數(shù)會首先被全部展開(有例外,見下文)。當展開后的宏參數(shù)被放進宏體時, 預(yù)處理器對新展開的宏體進行第二次掃描,并繼續(xù)展開。例如:

#define PARAM( x ) x 
  #define ADDPARAM( x ) INT_##x 
  PARAM( ADDPARAM( 1 ) ); 

因為ADDPARAM( 1 ) 是作為PARAM的宏參數(shù),所以先將ADDPARAM( 1 )展開為INT_1,然后再將INT_1放進PARAM。
例外情況是,如果PARAM宏里對宏參數(shù)使用了#或##,那么宏參數(shù)不會被展開:

#define PARAM( x ) #x 
  #define ADDPARAM( x ) INT_##x 

PARAM( ADDPARAM( 1 ) ); 將被展開為”ADDPARAM( 1 )”。

所以此時要得到“INT_1”的結(jié)果,必須加入一個中間宏:

#define PARAM(x) PARAM1(x)
#define PARAM1( x ) #x 

PARAM( ADDPARAM( 1 ) );此時的結(jié)果將會是“INT_1”。根據(jù)prescan原則,當ADDPARAM(1)傳入,會展開得到INT_1,然后將INT_1帶入PARAM1宏,最終得到“INT_1”的結(jié)果。

4. 接口宏

以下部分,摘自網(wǎng)上博客,僅作聲明。
C++的目標之一就是把類的聲明和定義分離開來,這對于項目的開發(fā)極其有利——這可以使開發(fā)人員不用看到類的實現(xiàn)就能知曉類的功能。但是,C++實現(xiàn)類的聲明與類定義的分離的方法會導(dǎo)致一些額外的工作——每個非內(nèi)聯(lián)函數(shù)的表示都需要寫兩次,一次在類聲明中,一次在類定義中。
代碼如下:

// .h File 
class Element 
{ 
void Tick (); 
};

// .cpp File 
void Element ::Tick () 
{ 
// todo 
}

由于Tick的標識在兩個地方都出現(xiàn)了,因此如果我們需要改變這個方法的參數(shù)的時候(改變函數(shù)名、返回類型或者加const),我們需要改變兩個地方。
當然通常這沒有什么工作量,但是有些情況下這個特性會帶來不少麻煩。
舉個例子,如果我們有一個叫做BaseClass的基類,有三個從BaseClass繼承而來的子類——D1、D2和D3.其中BaseClass聲明了一個虛函數(shù)Foo()并且有一個缺省實現(xiàn),并且D1、D2、D3中重載了Foo()函數(shù)。
現(xiàn)在,如果說我們給BaseClass::Foo()添加一個參數(shù),但是忘了給D3中做相應(yīng)的修改。麻煩來了——編譯可以通過,編譯器會把BaseClass::Foo(…)和D3::Foo()當成兩個完全不同的函數(shù)。當我們想通過虛函數(shù)機制來調(diào)用D3的Foo的時候,這就容易出一些問題。
UE4中光繼承自AActor類的類就有上千個,如果需要對AActor類做一個修改,那么如果使用傳統(tǒng)方法,我們還要針對上千個派生類進行修改,而且萬一有一個派生類沒有修改,編譯器也不會報錯!
這么看來,理想的情況是我們希望一個函數(shù)的表示只在一個地方存在,如果說只聲明BaseClass::Foo()一次,然后再它的派生類中不用再額外聲明Foo就好了。
而且在效率方面來說,在C++中使用繼承的時候我們經(jīng)常會使用很多淺層次的類繼承關(guān)系,一個父類往往有一堆子類。很多時候我們只需要把很多互不相關(guān)的功能集成到一個單獨的類繼承家族里面。
對于淺繼承來說,我們只是把開始的父類聲明為一個接口——也就是說它聲明了一些虛函數(shù)(大部分是純虛函數(shù))。在大多數(shù)情況下,我們會在這個類家族里面有一個基類以及其余的派生類。
如果說我們的基類有10個函數(shù),我們從這個基類派生了20個類,那么我們就需要額外做200個函數(shù)聲明。但是這些聲明的目的往往只是為了Implement基類中的那些方法而已,這就或多或少的容易使得頭文件不好維護。
傳統(tǒng)方法的實現(xiàn)
如果說我們有一個Animal的類,這個類被視為基類,我們希望從這個基類派生出不同的子類。在Animal中有3個純需函數(shù),如下所示:

class Animal 
{ 
public: 
virtual std :: string GetName () const = 0 ; 
virtual Vector3f GetPosition () const = 0; 
virtual Vector3f GetVelocity () const = 0; 
}; 

同時,這個基類擁有三個派生類——Monkey,Tiger,Lion。
那么我們?nèi)齻€方法的每一個都會在7個地方存在:Animal中一次,Monkey、Lion、Tiget的聲明和定義各一次。
然后假設(shè)我們做一個小改動——我們想將GetPosition和GetVelocity的返回類型改為Vector4f以適應(yīng)Transform變換,那么我們就要在7個地方進行修改:Animal的.h文件,Lion、Tiger和Monkey的.h文件和.cpp文件。
使用宏的實現(xiàn)
有一種很妙的處理方法就是將這些方法進行包裝,改成所謂接口宏的形式。我們可以試試看:

#define INTERFACE_ANIMAL(terminal)             \
public:                           \
  virtual std::string GetName() const ##terminal     \
  virtual IntVector GetPosition() const ##terminal    \
  virtual IntVector GetVelocity() const ##terminal    

#define BASE_ANIMAL   INTERFACE_ANIMAL(=0;)
#define DERIVED_ANIMAL INTERFACE_ANIMAL(;)

值得一提的是,##符號代表的是連接,\符號代表的是把下一行的連起來。
通過這些宏,我們就可以大大簡化Animal的聲明,還有所有從它派生的類的聲明了:

// Animal.h
class Animal
{
  BASE_ANIMAL ;
};



// Monkey.h
class Monkey : public Animal
{
  DERIVED_ANIMAL ;
};


// Lion.h
class Lion : public Animal
{
  DERIVED_ANIMAL ;
};


// Tiger.h
class Tiger : public Animal
{
  DERIVED_ANIMAL ;
};

相關(guān)文章

  • QT利用QProcess獲取計算機硬件信息

    QT利用QProcess獲取計算機硬件信息

    本文介紹利用QProcess獲取計算機的CPU、主板、硬盤等電腦相關(guān)硬件信息。文中的示例代碼講解詳細,對我們學(xué)習(xí)QT有一定的幫助,感興趣的可以了解一下
    2022-06-06
  • c語言判斷是否素數(shù)程序代碼

    c語言判斷是否素數(shù)程序代碼

    這篇文章主要介紹了c語言判斷是否素數(shù)的方法和問題,大家參考使用吧
    2013-11-11
  • C++標準庫實現(xiàn)WAV文件讀寫的操作

    C++標準庫實現(xiàn)WAV文件讀寫的操作

    本文將使用標準C++庫實現(xiàn)對數(shù)據(jù)為PCM格式的WAV文件的讀寫操作,只使用標準C++庫函數(shù),不依賴于其他的庫,對C++標準庫實現(xiàn)WAV文件讀寫相關(guān)知識感興趣的朋友一起看看吧
    2022-01-01
  • C語言標準時間與秒單位相互轉(zhuǎn)換

    C語言標準時間與秒單位相互轉(zhuǎn)換

    這篇文章主要介紹了C語言標準時間與秒單位相互轉(zhuǎn)換,秒單位與標準時間的轉(zhuǎn)換方式,這份代碼一般用在嵌入式單片機里比較多,比如:設(shè)置RTC時鐘的時間,從RTC里讀取秒單位時間后,需要轉(zhuǎn)換成標準時間顯示。下文分享需要的小伙伴可以參考一下
    2022-05-05
  • C++消息隊列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)

    C++消息隊列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收)

    這篇文章主要介紹了C++消息隊列(定義,結(jié)構(gòu),如何創(chuàng)建,發(fā)送與接收),消息隊列是一種先進先出的隊列型數(shù)據(jù)結(jié)構(gòu),實際上是系統(tǒng)內(nèi)核中的一個內(nèi)部鏈表
    2022-08-08
  • 使用C++的inipp庫處理配置文件.ini的示例詳解

    使用C++的inipp庫處理配置文件.ini的示例詳解

    一個ini文件由多個節(jié)section組成,每個節(jié)由多個鍵值對組成,本文給大家介紹了使用第三方庫inipp來操作ini文件,文中通過代碼示例講解的非常詳細,需要的朋友可以參考下
    2024-01-01
  • C++中多才多藝的 const

    C++中多才多藝的 const

    在C++中,關(guān)鍵字const可以用來修飾任何作用域內(nèi)的變量、函數(shù)參數(shù)、函數(shù)本體、函數(shù)返回值、成員函數(shù)、迭代器,也可以用來修飾指針本身和指針目標,可謂多才多藝,我們要詳細了解其內(nèi)部細節(jié),以及邏輯奧秘,讓這把多功能瑞士軍刀盡情發(fā)揮其作用,需要的朋友可以參考一下
    2021-09-09
  • 人臉檢測中AdaBoost算法詳解

    人臉檢測中AdaBoost算法詳解

    這篇文章主要為大家詳細介紹了人臉檢測中AdaBoost算法的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-01-01
  • C語言從代碼中加載動態(tài)鏈接庫過程解析

    C語言從代碼中加載動態(tài)鏈接庫過程解析

    這篇文章主要介紹了C語言從代碼中加載動態(tài)鏈接庫過程解析,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-12-12
  • C++判斷pe文件實例

    C++判斷pe文件實例

    這篇文章主要介紹了C++判斷pe文件的方法,包含了文件操作的具體實現(xiàn)方法,具有很好的參考借鑒價值,需要的朋友可以參考下
    2014-10-10

最新評論