新聞中心
類型萃取
類型萃取是基于c++中的模板特化來實現(xiàn)的,是對于模板特化的應(yīng)用。
以通用的拷貝函數(shù)為例
拷貝函數(shù),c++自帶的拷貝函數(shù)是俗稱的淺拷貝,淺拷貝對于一些內(nèi)置類型而言不會出錯,但對于一些自定義類型在拷貝的時候就會出現(xiàn)內(nèi)存訪問錯誤(中斷),想回顧淺拷貝的“同志”可以看https://blog.51cto.com/14233078/24425271.此方案雖然解決了拷貝問題,但是缺點也很明顯,在每一次拷貝數(shù)據(jù),都需要遍歷一遍,時間復(fù)雜度O(1)
#include
using namespace std;
#include
template
void Copy1(T* dst, T* src, size_t size)
{
memcpy(dst, src, sizeof(T)*size);
}
// 優(yōu)點:一定不會出錯
// 缺陷:O(N)
template
void Copy2(T* dst, T* src, size_t size)
{
for (size_t i = 0; i < size; ++i)
dst[i] = src[i];
}
bool IsPODType(const char* strType)
{
// 此處可以將所有的內(nèi)置類型枚舉出來
const char* strTypes[] = { "char", "short", "int", "long", "long long", "float", "double" };
for (auto e : strTypes)
{
if (strcmp(strType, e) == 0)
return true;
}
return false;
}
template
void Copy(T* dst, T* src, size_t size)
{
// 通過typeid可以將T的實際類型按照字符串的方式返回
if (IsPODType(typeid(T).name()))
{
// T的類型:內(nèi)置類型
memcpy(dst, src, sizeof(T)*size);
}
else
{
// T的類型:自定義類型---原因:自定義類型中可能會存在淺拷貝
for (size_t i = 0; i < size; ++i)
dst[i] = src[i];
}
}
void TestCopy()
{
int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int array2[10];
Copy(array2, array1, 10);
string s1[3] = { "1111", "2222", "3333" };
string s2[3];
Copy(s2, s1, 3);
}
int main()
{
TestCopy();
return 0;
}
C語言參與編譯的是.c文件,一個.c文件是一個編譯單元。
頭文件在預(yù)處理階段被展開,即,預(yù)處理器看見#include預(yù)處理指令的時候,就用相應(yīng)頭文件的內(nèi)容替換掉這個#include預(yù)處理指令(把頭文件內(nèi)容拷貝到.c文件中,然后刪除這條#include預(yù)處理指令)。
你應(yīng)該把頭文件看出是導(dǎo)出給外部模塊使用的接口,里面存放外部模塊需要使用的宏定義及函數(shù)原型。
在linux下,可以用gcc -E查看預(yù)處理之后的文件。
頭文件中的函數(shù)原型是提供給編譯器作為函數(shù)原型檢查的,對于不是本源文件中的函數(shù),編譯過程中并不會產(chǎn)生實際的調(diào)用代碼(函數(shù)調(diào)用需要知道確切的函數(shù)地址),只是在相應(yīng)的地方做個標(biāo)記,表示在這里需要調(diào)用某個函數(shù)。編譯完成產(chǎn)生的是匯編代碼。
如上所述,編譯產(chǎn)生的匯編代碼并不能直接運行,因為外部函數(shù)調(diào)用的地方還沒給予確切的函數(shù)地址。這個工作由鏈接過程完成。鏈接器會查找其它源文件所產(chǎn)生的匯編代碼,進而找到正確的函數(shù)調(diào)用地址,然后用這個地址替換掉在編譯時做的標(biāo)記。完成這一步后,程序就可以實際運行了。
因此,.h是根本不會被編譯的,它如果被包含,則會被預(yù)處理器將其內(nèi)容一分不差的拷貝到.c文件中,.編譯器編譯的是拷貝后的這個.c文件。
2.分文件管理:
因為頭文件在預(yù)處理階段就已完成,所以不會降低代碼效率,因此解決1中代碼效率低的問題
頭文件
#pragma once
#include
using namespace std;
#include
//來自自定義類型
struct TrueType
{};
// 對應(yīng)自定義類型
struct FalseType
{};
//隱示實例化
template
struct TypeTraits
{
typedef FalseType PODTYPE; // plain old data
};
//顯示實例化
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
template<>
struct TypeTraits
{
typedef TrueType PODTYPE;
};
void TestCopy();
源代碼
#include"Type_extraction.h"
template
void Copy(T* dst, T* src, size_t size, TrueType)
{
// T的類型:內(nèi)置類型
memcpy(dst, src, sizeof(T)*size);
}
template
void Copy(T* dst, T* src, size_t size, FalseType)
{
// T的類型:自定義類型---原因:自定義類型中可能會存在淺拷貝
for (size_t i = 0; i < size; ++i)
dst[i] = src[i];
}
template
void Copy(T* dst, T* src, size_t size)
{
Copy(dst, src, size, TypeTraits::PODTYPE());
}
void TestCopy()
{
int array1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int array2[10];
Copy(array2, array1, 10);
string s1[3] = { "1111", "2222", "3333" };
string s2[3];
Copy(s2, s1, 3);
}
測試文件main.c
#include"Type_extraction.h"
int main()
{
TestCopy();
return 0;
}
模板的聲明和定義必須放在一個文件原因
https://blog.csdn.net/chigusakawada/article/details/78752668
顯示實例化,隱式實例化概念
https://blog.csdn.net/qiujianjian/article/details/84792608
另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機、免備案服務(wù)器”等云主機租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。
當(dāng)前名稱:C++類型萃?。ǚ治募芾恚?創(chuàng)新互聯(lián)
標(biāo)題網(wǎng)址:http://www.dlmjj.cn/article/dogidc.html