锘??xml version="1.0" encoding="utf-8" standalone="yes"?>
]]>
鐢ㄤ綅榪愮畻鏉ヨ〃紺烘妸涓涓礋鏁拌漿鎹㈡垚zig-zag緙栫爜錛屽氨鏄?span class="pun">
int32鏄細(n << 1) ^ (n >> 31)
int64鏄細(n << 1) ^ (n >> 63)
涔熷氨鏄錛屽鏋滄槸璐熸暟錛屽浜?2浣嶆渶澶氳兘鐪佸幓30鏍鹼紙鍏朵腑1鏍兼槸絎﹀彿浣嶏紝鍙︿竴涓唬琛ㄦ渶灝忓?錛屾澶勫亣璁?#8220;姝h礋0”涓嶅悎娉曪級銆傚悓鐞嗭紝64浣嶆渶澶氳兘鐪佸幓62浣嶃傚綋鐒舵瘮杈冩瀬绔殑鏄墍鏈夌殑浣嶆暟閮借鐢ㄤ笂浜嗐?br>
]]>
棣栧厛浠涔堟槸Wow64錛熷緢澶氭湅鍙嬩竴鐪嬪埌64灝辮涓鴻繖涓柟娉曟槸鍒ゆ柇褰撳墠緋葷粺鏄惁鏄?4bit鐨勶紝鍏跺疄涓嶇劧銆俉ow64鏄疻indows-On-Windows64鐨勬剰鎬濓紝瀹冩槸鎸囧湪64浣嶇殑鎿嶄綔緋葷粺涓婏紙涓嶆槸鎸?4浣嶇殑CPU錛夎繍琛?2浣嶅簲鐢ㄧ▼搴忕殑鍏煎騫沖彴銆?/p>
涓嬮潰鏄疢SDN涓竴孌礗sWow64鐨勫簲鐢ㄧ▼搴忥細
BOOL IsWow64() { typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); LPFN_ISWOW64PROCESS fnIsWow64Process; BOOL bIsWow64 = FALSE; fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress( GetModuleHandle(_T("kernel32")), "IsWow64Process"); if (NULL != fnIsWow64Process) { fnIsWow64Process(GetCurrentProcess(),&bIsWow64); } return bIsWow64; }
涓嬮潰鐨勪唬鐮佺敤鏉ユ嫻嬭繖涓▼搴忕殑緇撴灉錛?/p>
if( IsWow64() == TRUE ) { _tprintf(_T("IsWow64() == TRUE\n")); } else { _tprintf(_T("IsWow64() == FALSE\n")); }
璁╂垜浠紪璇戜竴涓嬭繖涓▼搴忋?/p>
鎴戜滑闇瑕佺殑鏄?4浣嶇殑鎿嶄綔緋葷粺錛屾瘮濡俋P64bit錛學indows 2008 R2絳夐兘鏄?4bit鎿嶄綔緋葷粺銆?/p>
鍦?4浣嶇殑鎿嶄綔緋葷粺涓婅繍琛岀殑kernel32.dll涓紝灝嗕細瀹炵幇IsWow64Process鏂規硶錛岃屽湪32浣嶇郴緇熶腑鎻愪緵鐨刱ernel32.dll涓垯娌℃湁鎻愪緵鐩稿叧鍑芥暟鐨勫疄鐜般?/p>
姣旇緝榪鋒儜浜虹殑鍒欐槸bIsWow64錛屽叾瀹炰粩緇嗙湅MSDN涓殑Remark錛屼細鍙戠幇錛?/p>
If the application is a 64-bit application running under 64-bit Windows, the Wow64Process parameter is set to FALSE.涔熷氨鏄64浣嶅簲鐢ㄧ▼搴忚窇鍦?4浣嶇殑鎿嶄綔緋葷粺涓婏紝bIsWow64鐨勫煎皢鏄疐ALSE鑰屼笉鏄疶RUE銆?
鍥犳鎴戜滑闇瑕佸垎鍒皢鎴戜滑鐨勭▼搴忕紪璇戞垚Win32騫沖彴鍜寈64騫沖彴鐨勶紝濡傛灉浣犵敤Visual Studio榪涜緙栬瘧錛岄粯璁ゅ畨瑁呭垯鍙寘鍚?2浣嶇殑緙栬瘧鍣?閾炬帴鍣紝鍗充究浣犳槸鍦?4浣嶆搷浣滅郴緇熶笂瀹夎錛屼篃鏄竴鏍風殑銆備綘闇瑕佸湪VC++鑺傜偣涓嬪嬀閫墄64閫夐」鎵嶅彲浠ワ紝Itanium鍒欓渶瑕佸湪Server騫沖彴涓嬪畨瑁呮墠鍙嬀閫夈傜劧鍚庡湪緙栬瘧鐨勬椂鍊欙紝鍒嗗埆閫夋嫨Win32鍜寈64榪涜緙栬瘧銆?
緙栬瘧鍚庯紝榪愯錛岀粨鏋滃鎴戜滑鍒嗘瀽鐨勪竴鏍鳳細
鍦?4浣嶇郴緇熶笂榪愯Win32緙栬瘧閰嶇疆鐨勭粨鏋滄槸IsWow64() == TRUE錛岃寈64緙栬瘧閰嶇疆鐨勭粨鏋滄槸IsWow64() == FALSE銆?
濡傛灉鎯寵鐭ラ亾褰撳墠緋葷粺鏄惁鏄?4浣嶇殑錛屽垯鍙互閫氳繃涓嬮潰鐨勬柟娉曪細
BOOL Is64bitSystem() { SYSTEM_INFO si; GetNativeSystemInfo(&si); if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 || si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 ) { return TRUE; } else { return FALSE; } }
娉ㄦ剰錛氶渶瑕佹敞鎰忔槸GetNativeSystemInfo 鍑芥暟浠嶹indows XP 寮濮嬫墠鏈夛紝 鑰?IsWow64Process 鍑芥暟浠?Windows XP with SP2 浠ュ強 Windows Server 2003 with SP1 寮濮嬫墠鏈夈?
鍔ㄦ佽繛鎺ュ簱鐨勫垱寤烘楠わ細
涓銆佸垱寤篘on-MFC DLL鍔ㄦ侀摼鎺ュ簱
1銆佹墦寮File 鈥?gt; New 鈥?gt; Project閫夐」錛岄夋嫨Win32 Dynamic-Link Library 鈥?gt;sample project 鈥?gt;宸ョ▼鍚嶏細DllDemo
2銆佹柊寤轟竴涓?h鏂囦歡DllDemo.h
#ifdef DllDemo_EXPORTS
#define DllAPI __declspec(dllexport)
#else
#define DllAPI __declspec(dllimport)
extern "C" //鍘熸牱緙栬瘧
{
DllAPI int __stdcall Max(int a,int b); //__stdcall浣塊潪C/C++璇█鍐呰兘澶熻皟鐢ˋPI
}
#endif
3銆佸湪DllDemo.cpp鏂囦歡涓鍏llDemo.h鏂囦歡錛屽茍瀹炵幇Max(int,int)鍑芥暟
#include "DllDemo.h"
DllAPI int __stdcall Max(int a,int b)
{
if(a==b)
return NULL;
else if(a>b)
return a;
else
return b;
}
4銆佺紪璇戠▼搴忕敓鎴愬姩鎬佽繛鎺ュ簱
浜屻佺敤.def鏂囦歡鍒涘緩鍔ㄦ佽繛鎺ュ簱DllDemo.dll
1銆佸垹闄llDemo宸ョ▼涓殑DllDemo.h鏂囦歡銆?
2銆佸湪DllDemo.cpp鏂囦歡澶達紝鍒犻櫎 #include DllDemo.h璇彞銆?
3銆佸悜璇ュ伐紼嬩腑鍔犲叆涓涓枃鏈枃浠訛紝鍛藉悕涓篋llDemo.def騫跺啓鍏ュ涓嬭鍙ワ細
LIBRARY MyDll
EXPORTS
Max@1
4銆佺紪璇戠▼搴忕敓鎴愬姩鎬佽繛鎺ュ簱銆?
鍔ㄦ侀摼鎺ョ殑璋冪敤姝ラ錛?/strong>
涓銆侀殣寮忚皟鐢?/strong>
1銆佸緩绔婦llCnslTest宸ョ▼
2銆佸皢鏂囦歡DllDemo.dll銆丏llDemo.lib鎷瘋礉鍒癉llCnslTest宸ョ▼鎵鍦ㄧ殑鐩綍
3銆佸湪DllCnslTest.h涓坊鍔犲涓嬭鍙ワ細 #define DllAPI __declspec(dllimport) 4銆佸湪DllCnslTest.cpp鏂囦歡涓坊鍔犲涓嬭鍙ワ細 #include "DllCnslTest.h"http://鎴栬?#include "DllDemo.h" 5銆佺紪璇戝茍鐢熸垚搴旂敤紼嬪簭DllCnslTest.exe
浜屻佹樉寮忚皟鐢?/strong>
1銆佸緩绔婦llWinTest宸ョ▼銆?
2銆佸皢鏂囦歡DllDemo.dll鎷瘋礉鍒癉llWinTest宸ョ▼鎵鍦ㄧ殑鐩綍鎴朩indows緋葷粺鐩綍涓嬨?
3銆佺敤vc/bin涓嬬殑Dumpbin.exe鐨勫皬紼嬪簭錛屾煡鐪婦LL鏂囦歡(DllDemo.dll)涓殑鍑芥暟緇撴瀯銆?
4銆佷嬌鐢ㄧ被鍨嬪畾涔夊叧閿瓧typedef錛屽畾涔夋寚鍚戝拰DLL涓浉鍚岀殑鍑芥暟鍘熷瀷鎸囬拡銆?
渚嬶細 typedef int(*lpMax)(int a,int b); //姝よ鍙ュ彲浠ユ斁鍦?h鏂囦歡涓?/p> 5銆侀氳繃LoadLibray()灝咲LL鍔犺澆鍒板綋鍓嶇殑搴旂敤紼嬪簭涓茍榪斿洖褰撳墠DLL鏂囦歡鐨勫彞鏌勩?
渚嬶細 HINSTANCE hDll; //澹版槑涓涓狣ll瀹炰緥鏂囦歡鍙ユ焺 6銆侀氳繃GetProcAddress()鍑芥暟鑾峰彇瀵煎叆鍒板簲鐢ㄧ▼搴忎腑鐨勫嚱鏁版寚閽堛?
渚嬶細 lpMax Max; 7銆佸嚱鏁拌皟鐢ㄥ畬姣曞悗錛屼嬌鐢‵reeLibrary()鍗歌澆DLL鏂囦歡銆?pre> FreeLibrary(hDll); 8銆佺紪璇戝茍鐢熸垚搴旂敤紼嬪簭DllWinTest.exe
娉細鏄懼紡閾炬帴搴旂敤紼嬪簭緙栬瘧鏃朵笉闇瑕佷嬌鐢ㄧ浉搴旂殑Lib鏂囦歡銆?/p>
涓嬭澆錛?font style="background-color: #cccccc">Visual Studio 2008楠岃瘉閫氳繃錛夛細http://www.shnenglu.com/Files/mymsdn/DllCnsTest.7z
#pragma comment(lib錛?DllDemo.lib") //鍦ㄧ紪杈戝櫒link鏃訛紝閾炬帴鍒癉llDemo.lib鏂囦歡
extern "C"
{
DllAPI int __stdcall Max(int a,int b);
}
void main()
{
int value;
value = Max(2,9);
printf("The Max value is %d\n",value);
}
hDll = LoadLibrary("DllDemo.dll");//瀵煎叆DllDemo.dll鍔ㄦ佽繛鎺ュ簱
Max = (lpMax)GetProcAddress(hDLL,"Max");
int value;
value = Max(2,9);
printf("The Max value is %d",value);
]]>
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \紱佹闅愬紡鏋勯狅紝鍒欏彲浠ュ皢榛樿鏋勯犲嚱鏁伴殣钘忚搗鏉ワ紝鍦ㄥぇ澶氭暟緙栬瘧鍣ㄤ腑涔熷彲浠ュ鏋勯犲嚱鏁板鍔爀xplicit鍏抽敭瀛楁潵閬垮厤闅愬紡鏋勯犮?
private: \
TypeName(const TypeName&); \
TypeName& operator=(const TypeName&)
#define DISALLOW_IMPLICIT_CONSTRUCTORS(TypeName) \鏇村瑙i噴璇﹁銆奙ore Effective C++銆?
private: \
TypeName(); \
DISALLOW_COPY_AND_ASSIGN(TypeName)
// keyword__declspec.cpp : 瀹氫箟鎺у埗鍙板簲鐢ㄧ▼搴忕殑鍏ュ彛鐐廣? // // ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.chs/kernel_d/hh/Kernel_d/64bitAMD_6db3322a-fe6d-4287-9eda-a9c1378e715d.xml.htm // The sizeof value for any structure is the offset of the final member, // plus that member's size, rounded up to the nearest multiple of the largest // member alignment value or the whole structure alignment value, // whichever is greater. #include "stdafx.h" __declspec( align( 32) ) struct Struct__declspec_1 { int a; int b; }; __declspec( align( 32) ) struct Struct__declspec_2 { __declspec( align( 64) ) int a; int b; }; __declspec( align( 8 ) ) struct Struct__declspec_3 { int a; //4 bytes int b; //4 bytes int c; //4 bytes }; __declspec( align( 8 ) ) struct Struct__declspec_4 { int a; //4 bytes int b; //4 bytes }; struct StructNormal { int a; //4 bytes int b; //4 bytes int c; //4 bytes }; int _tmain(int argc, _TCHAR* argv[]) { printf( "sizeof Struct__declspec_1 is %d.\n", sizeof( Struct__declspec_1 )); //32 printf( "sizeof Struct__declspec_2 is %d.\n", sizeof( Struct__declspec_2 )); //64 printf( "sizeof Struct__declspec_3 is %d.\n", sizeof( Struct__declspec_3 )); //16 printf( "sizeof Struct__declspec_4 is %d.\n", sizeof( Struct__declspec_4 )); //8 printf( "sizeof StructNormal is %d.\n", sizeof( StructNormal )); //12 return 0; }
鍏跺疄榪欎釜鏃跺欏彲鑳芥槸涓浜沄ista浠ヤ笂鐗堟湰鐨凮S鎵鎻愪緵鐨勬柊鍔熻兘寮曡搗鐨勯檺鍒躲傚氨褰撳墠鐨勮繖涓緥瀛愯岃█錛屾槸鍥犱負緙栬瘧鐨勬椂鍊欙紝鍚敤鐢ㄦ埛甯愭埛鎺у埗(UAC)榛樿涓衡滄槸鈥濇墍鑷達紝灝嗚В鍐蟲柟妗堝唴鎵鏈夊伐紼嬮変腑錛屽彸閿睘鎬э紝淇敼鈥滈厤緗睘鎬р?>鈥滈摼鎺ュ櫒鈥?>鈥滄竻鍗曟枃浠垛?>鈥滃惎鐢ㄧ敤鎴峰笎鎴鋒帶鍒?UAC)鈥濅負鈥滃惁鈥濓紝閲嶆柊鐢熸垚瑙e喅鏂規錛屽嵆鍙?/p>
浠婃櫄鍦ㄧ被涓姞鍏ヤ袱涓暟緇勭敤鏉ュ仛璁℃暟錛屽洜涓轟箣鍓嶄唬鐮佹湁鎵鏀瑰姩錛孷S緙栬瘧錛堝閲忥級鐨勭粨鏋滃眳鐒跺嚭鐜頒簡鏃犳暟嬈$殑紼嬪簭宕╂簝錛屽鎴戜竴搴︽鐤戞槸涓嶆槸鎴戠殑鏁扮粍鍐欑殑鏈夐棶棰樸傚洤銆傛渶鍚庢棤濂堜箣涓嬶紝鐐逛簡閲嶆柊鐢熸垚錛屽眳鐒墮『鍒╅氳繃浜嗭紝寰堢敓姘旓紝鎰ゆ掍腑銆?/p>
浣嗘槸鍙﹀鍗村彂鐜頒簡涓涓棶棰橈紝涔熷氨鏄綋size_t鐢ㄤ綔寰幆鐨勬椂鍊欍傚洜涓轟互鍓嶉兘鏄敤int鍋氬驚鐜殑錛岀幇鍦ㄦ崲鎴恥nsigned int錛堜篃灝辨槸size_t錛夊悗錛屼竴涓嬪瓙娌″弽搴旇繃鏉ワ紝灝遍『鎵嬭繖涔堝啓浜嗭細
for( size_t i = MAX - 1; i >= 0; --i)
{
//鈥︹?/p>
}
涔嶄竴鐪嬩技涔庢病鍟ラ棶棰橈紝鍥犱負鎴戝驚鐜唴鐨勪唬鐮佹槸鍒犻櫎璧勬簮鐨勶紝鍥犳紼嬪簭涔熼棰戝穿婧冦?/p>
step over鐨勭粨鏋滄墠璁╀漢鎯婅錛屽洜涓哄綋size_t i = 0鐨勬椂鍊欙紝--i鐨勭粨鏋滄槸鏃犵┓澶э紝鑰屾棤絀峰ぇ鍒欒偗瀹氭弧瓚砳>=0鐨勬潯浠訛紝鎵浠ュ綋鎴戜滑鏈熷緟紼嬪簭鍋滀綇鐨勬椂鍊欙紝紼嬪簭鏄笉浼氬仠浣忕殑銆?/p>
淇鐨勬柟寮忥細
1銆佷嬌鐢ㄦ鍚戦亶鍘嗐?/p>
2銆佸鍔犲垽鏂潯浠訛紙i>=0 && i < MAX錛夛紝浣嗚繖閲屼篃鍙兘瀛樺湪闂錛屽洜涓簊ize_t鍙兘琚畾涔変負unsigned int錛屼絾鏄疢AX鍙兘鏄釜鏇村ぇ鐨勬暟錛屾瘮濡倁nsigned long long錛屽綋鐒惰繖鏍風殑姣旇緝涓嶆槸寰堟湁鎰忎箟錛屾垨鑰呬細瀹炵幇涓浜涜漿鎹紝浣嗘槸濡傛灉榪欑鎯呭喌鍙戠敓鐨勮瘽錛岀▼搴忓彲鑳借繕鏄細閫氳繃涓涓殢鏈虹殑i榪涘叆鍒頒竴涓湭鐭ョ殑絀洪棿涓紝浠庤岄犳垚宕╂簝銆傝屼笖澧炲姞鍒ゆ柇鏉′歡涔熶嬌寰楃▼搴忕殑榪愯鎴愭湰鎻愰珮銆?/p>
/* * cpp_traits.cpp * * Created on: 2010-4-26 * Author: volnet@tom.com */ #include <iostream> // kinds of types for overloading. struct undefined_type {}; struct int32_type {}; struct int64_type {}; // typedef some has_trivial_* for difference types. template <class T> struct type_traits { typedef undefined_type has_trivial_type; }; // define the partial specialization functions. template <> struct type_traits<int> { typedef int32_type has_trivial_type; }; template <> struct type_traits<long> { typedef int64_type has_trivial_type; }; // the dispatcher method for all kinds of types. template <class T> void type_detect(T& p){ typedef typename type_traits<T>::has_trivial_type trivial_type; type_detect(p, trivial_type()); } // define the functions for dispatching. template <class T> void type_detect(T& p, undefined_type) { std::cout << p; std::cout << " // It's a undefined type, we have NOT found the dispatcher function." << std::endl; } template <class T> void type_detect(T& p, int32_type) { std::cout << p; std::cout << " // It's a int32" << std::endl; } template <class T> void type_detect(T& p, int64_type) { std::cout << p; std::cout << " // It's a int64" << std::endl; } int main(void) { int int32num = 2010; type_detect(int32num); long int64num = 2010L; type_detect(int64num); std::string str = "2010"; type_detect(str); std::cout << "-------end of program." << std::endl; return EXIT_SUCCESS; }
澶ч儴鍒嗕漢閮藉惉璇磋繃auto_ptr鎸囬拡錛屼絾鏄茍闈炴墍鏈変漢閮芥瘡澶╀嬌鐢ㄥ畠銆備笉浣跨敤瀹冩槸涓嶆槑鏅虹殑錛堝彲鑰葷殑錛夛紝鍥犱負auto_ptr鐨勮璁″垵琛鋒槸涓轟簡瑙e喅C++璁捐鍜岀紪鐮佺殑鏅亶闂錛屽皢瀹冪敤濂藉彲浠ュ啓鍑烘洿鍋ュ.鐨勪唬鐮併傛湰鏂囨寚鍑哄浣曟紜嬌鐢╝uto_ptr浠ヤ嬌紼嬪簭鍙樺緱瀹夊叏錛屼互鍙婂浣曢伩寮鍗遍櫓錛岃屼笉鏄竴鑸嬌鐢╝uto_ptr鐨勬伓涔犳墍鑷寸殑鍒涘緩闂存瓏鎬у拰闅句互璇婃柇鐨勯棶棰樸?
auto_ptr鍙槸璁歌澶氬鏅鴻兘鎸囬拡涓殑涓縐嶃傝澶氬晢涓氬簱鎻愪緵璁稿鏇村己澶х殑鏅鴻兘鎸囬拡錛屽彲浠ュ畬鎴愭洿澶氱殑浜嬫儏銆備粠鍙互綆$悊寮曠敤璁℃暟鍒版彁渚涙洿鍏堣繘鐨勪唬鐞嗘湇鍔$瓑銆傚簲璇ユ妸auto_ptr璁や負鏄櫤鑳芥寚閽堜腑鐨勭鐗笶scort[娉ㄩ噴]錛氫竴涓熀浜庣畝鍗曚笖閫氱敤鐩殑鐨勬櫤鑳芥寚閽堬紝鏃㈡病鏈夊皬鍙戞槑涔熸病鏈変赴瀵岀殑鐗規畩鐩殑鏇翠笉闇瑕侀珮鎬ц兘錛屼絾鏄兘灝嗚澶氭櫘閫氱殑浜嬫儏鍋氬ソ錛屽茍涓旇兘澶熼傚悎鏃ュ父浣跨敤鐨勬櫤鑳芥寚閽堛?
auto_ptr鍋氳繖鏍蜂竴浠朵簨錛氭嫢鏈変竴涓姩鎬佸垎閰嶅唴瀛樺璞★紝騫朵笖鍦ㄥ畠涓嶅啀闇瑕佺殑鏃跺欏飽琛岃嚜鍔ㄦ竻鐞嗙殑鑱岃矗銆傝繖閲屾湁涓病鏈変嬌鐢╝uto_ptr鎸囬拡鐨勪笉瀹夊叏鐨勪緥瀛愶細
// Example 1(a): Original code // void f() { T* pt( new T ); /*...more code...*/ delete pt; }
鎴戜滑姣忓ぉ閮藉儚榪欐牱鍐欎唬鐮侊紝濡傛灉f()鍙槸涓涓笁琛岀▼搴忥紝涔熸病鍋氫粈涔堝浣欑殑浜嬫儏錛岃繖鏍峰仛褰撶劧鍙互寰堝ソ宸ヤ綔銆備絾鏄鏋渇()娌℃湁鎵цdelete璇彞錛屾瘮濡傜▼搴忔彁鍓嶈繑鍥烇紙return錛変簡錛屾垨鑰呭湪鎵ц鐨勬椂鍊欐姏鍑哄紓甯鎬簡錛岀劧鍚庡氨瀵艱嚧宸茬粡鍒嗛厤鐨勫璞℃病鏈夎鍒犻櫎錛屽洜姝ゆ垜浠氨鏈変簡涓涓粡鍏哥殑鍐呭瓨娉勬紡銆?
涓涓嬌Example錛?錛夊畨鍏ㄧ殑鍔炴硶鏄敤涓涓滄櫤鑳解濈殑鎸囬拡鎷ユ湁榪欎釜鎸囬拡錛屽綋閿姣佺殑鏃跺欙紝鍒犻櫎閭d釜琚寚鐨勮嚜鍔ㄥ垎閰嶇殑瀵硅薄銆傚洜涓鴻繖涓櫤鑳芥寚閽堣綆鍗曞湴鐢ㄤ負鑷姩瀵硅薄錛堣繖灝辨槸錛屽綋瀹冪寮瀹冪殑浣滅敤鍩熺殑鏃跺欒嚜鍔ㄩ攢姣佸璞★級錛屾墍浠ュ畠琚О浣溾滆嚜鍔ㄢ濇寚閽堛?
// Example 1(b): Safe code, with auto_ptr // void f() { auto_ptr<T> pt( new T ); /*...more code...*/ } // cool: pt's destructor is called as it goes out // of scope, and the object is deleted automatically
鐜板湪榪欐浠g爜灝嗕笉浼氬啀T瀵硅薄涓婂彂鐢熸硠婕忎簡錛屼笉蹇呭湪鎰忚繖涓柟娉曟槸姝e父閫鍑鴻繕鏄紓甯擱鍑猴紝鍥犱負pt鐨勬瀽鏋勫嚱鏁板皢鎬繪槸鍦ㄥ爢鏍堝脊鍑虹殑鏃跺欒璋冪敤銆傛竻鐞嗗伐浣滃皢鑷姩榪涜銆?/p>
鏈鍚庯紝浣跨敤auto_ptr鍜屼嬌鐢ㄥ唴寤烘寚閽堜竴鏍峰湴瀹規槗錛屽鏋滆鈥滄敹鍥炩濊祫婧愬茍涓斿啀嬈℃墜鍔ㄧ鐞嗙殑璇濓紝鎴戜滑鍙互璋冪敤release()錛?/p>
// Example 2: Using an auto_ptr // void g() { T* pt1 = new T; // right now, we own the allocated object // pass ownership to an auto_ptr auto_ptr<T> pt2( pt1 ); // use the auto_ptr the same way // we'd use a simple pointer *pt2 = 12; // same as "*pt1 = 12;" pt2->SomeFunc(); // same as "pt1->SomeFunc();" // use get() to see the pointer value assert( pt1 == pt2.get() ); // use release() to take back ownership T* pt3 = pt2.release(); // delete the object ourselves, since now // no auto_ptr owns it any more delete pt3; } // pt2 doesn't own any pointer, and so won't // try to delete it... OK, no double delete
鏈鍚庯紝鎴戜滑鍙互浣跨敤auto_ptr鐨剅eset()鏂規硶灝哸uto_ptr閲嶇疆鍚戝彟涓涓璞°傚鏋渁uto_ptr宸茬粡鑾峰緱涓涓璞★紝榪欎釜榪囩▼灝卞儚鏄畠鍏堝垹闄ゅ凡緇忔嫢鏈夌殑瀵硅薄錛屽洜姝よ皟鐢╮eset()錛屽氨鍍忔槸鍏堥攢姣佷簡auto_ptr錛岀劧鍚庨噸寤轟簡涓涓柊鐨勫茍鎷ユ湁璇ユ柊瀵硅薄錛?
// Example 3: Using reset() // void h() { auto_ptr<T> pt( new T(1) ); pt.reset( new T(2) ); // deletes the first T that was // allocated with "new T(1)" } // finally, pt goes out of scope and // the second T is also deleted
鍚屾牱錛宎uto_ptr涔熷彲浠ヨ鐢ㄤ簬瀹夊叏鍦板寘瑁呮寚閽堟暟鎹垚鍛樸傝冭檻涓嬮潰浣跨敤Pimpl idiom錛堟垨鑰咃紝緙栬瘧鍣ㄩ槻鐏錛夌殑渚嬪瓙錛?sup>[1]
// Example 4(a): A typical Pimpl // // file c.h // class C { public: C(); ~C(); /*...*/ private: class CImpl; // forward declaration CImpl* pimpl_; }; // file c.cpp // class C::CImpl { /*...*/ }; C::C() : pimpl_( new CImpl ) { } C::~C() { delete pimpl_; }
綆鍗曞湴璇達紝灝辨槸C鐨勭鏈夌粏鑺傝瀹炵幇涓轟竴涓崟鐙殑瀵硅薄錛岃棌鍖夸簬涓涓寚閽堜箣涓傝鎬濊礬瑕佹眰C鐨勬瀯閫犲嚱鏁拌礋璐d負闅愯棌鍦ㄧ被鍐呴儴鐨勮緟鍔┾淧impl鈥濆璞″垎閰嶅唴瀛橈紝騫朵笖C鐨勬瀽鏋勫嚱鏁拌礋璐i攢姣佸畠銆備嬌鐢╝uto_ptr錛屾垜浠細鍙戠幇榪欓潪甯稿鏄擄細
// Example 4(b): A safer Pimpl, using auto_ptr // // file c.h // class C { public: C(); /*...*/ private: class CImpl; // forward declaration auto_ptr<CImpl> pimpl_; }; // file c.cpp // class C::CImpl { /*...*/ }; C::C() : pimpl_( new CImpl ) { }
鐜板湪錛屾瀽鏋勫嚱鏁頒笉闇瑕佹媴蹇冨垹闄impl_鎸囬拡浜嗭紝鍥犱負auto_ptr灝嗚嚜鍔ㄥ鐞嗗畠銆備簨瀹炰笂錛屽鏋滄病鏈夊叾瀹冮渶瑕佹樉寮忓啓鏋愭瀯鍑芥暟鐨勫師鍥狅紝鎴戜滑瀹屽叏涓嶉渶瑕佽嚜瀹氫箟鏋愭瀯鍑芥暟銆傛樉鐒訛紝榪欐瘮鎵嬪姩綆$悊鎸囬拡瑕佸鏄撳緱澶氾紝騫朵笖灝嗗璞℃墍鏈夋潈鍖呭惈榪涘璞℃槸涓涓笉閿欑殑涔犳儻錛岃繖姝f槸auto_ptr鎵鎿呴暱鐨勩傛垜浠皢鍦ㄦ渶鍚庡啀嬈″洖欏捐繖涓緥瀛愩?
瀹冩湰韜緢婕備寒錛屽茍涓斿仛寰楅潪甯稿ソ錛氫粠鍑芥暟浼犲叆鎴栦紶鍑?span style="font-family: 'Courier New'" class="Code">auto_ptrs錛屾槸闈炲父鏈夌敤鐨勶紝姣斿鍑芥暟鐨勫弬鏁版垨鑰呰繑鍥炲箋?/p>
璁╂垜浠湅鐪嬩負浠涔堬紝棣栧厛鎴戜滑鑰冭檻褰撴嫹璐漚uto_ptr鐨勬椂鍊欎細鍙戠敓浠涔堬細涓涓猘uto_ptr鑾峰緱涓涓嫢鏈夋寚閽堢殑瀵硅薄錛屽茍涓斿湪鍚屼竴鏃墮棿鍙厑璁告湁涓涓猘uto_ptr鍙互鎷ユ湁榪欎釜瀵硅薄銆傚綋浣犳嫹璐濅竴涓猘uto_ptr鐨勬椂鍊欙紝浣犺嚜鍔ㄥ皢婧恆uto_ptr鐨勬墍鏈夋潈錛屼紶閫掔粰鐩爣auto_ptr錛涘鏋滅洰鏍嘺uto_ptr宸茬粡鎷ユ湁浜嗕竴涓璞★紝榪欎釜瀵硅薄灝嗗厛琚噴鏀俱傚湪鎷瘋礉瀹屼箣鍚庯紝鍙湁鐩爣auto_ptr鎷ユ湁鎸囬拡錛屽茍涓旇礋璐e湪鍚堥傜殑鏃墮棿閿姣佸畠錛岃屾簮灝嗚璁劇疆涓虹┖錛坣ull錛夛紝騫朵笖涓嶈兘鍐嶈褰撲綔鍘熸湁鎸囬拡鐨勪唬琛ㄦ潵浣跨敤銆?
渚嬪錛?/p>
// Example 5: Transferring ownership from // one auto_ptr to another // void f() { auto_ptr<T> pt1( new T ); auto_ptr<T> pt2; pt1->DoSomething(); // OK pt2 = pt1; // now pt2 owns the pointer, // and pt1 does not pt2->DoSomething(); // OK } // as we go out of scope, pt2's destructor // deletes the pointer, but pt1's does nothing
浣嗘槸瑕侀伩鍏嶉櫡闃卞啀嬈′嬌鐢ㄥ凡緇忓け鍘繪墍鏈夋潈鐨刟uto_ptr錛?
// Example 6: Never try to do work through // a non-owning auto_ptr // void f() { auto_ptr<T> pt1( new T ); auto_ptr<T> pt2; pt2 = pt1; // now pt2 owns the pointer, and // pt1 does not pt1->DoSomething(); // error! following a null pointer }
璋ㄨ浜庡績錛屾垜浠幇鍦ㄧ湅鐪媋uto_ptr濡備綍鍦ㄦ簮鍜岃皟鐢ㄨ呬箣闂村伐浣溿傗滄簮鈥濊繖閲屾槸鎸囦竴涓嚱鏁幫紝鎴栬呭叾瀹冨垱寤轟竴涓柊璧勬簮鐨勬搷浣滐紝騫朵笖閫氬父灝嗙Щ浜ゅ嚭璧勬簮鐨勬墍鏈夋潈銆備竴涓滆皟鐢ㄨ呪濆嚱鏁板弽杞繖涓叧緋伙紝涔熷氨鏄幏寰楀凡緇忓瓨鍦ㄥ璞$殑鎵鏈夋潈錛堝茍涓旈氬父榪樿礋璐i噴鏀懼畠錛夈傝屼笉鏄湁涓涓簮鍜岃皟鐢ㄨ咃紝榪斿洖騫朵笖鍒╃敤涓涓澶存寚閽堬紙璇戣呮敞錛氳屼笉鏄嬌鐢ㄤ竴涓眬閮ㄥ彉閲忔潵浼犻掕繖涓寚閽堬級錛岃櫧鐒訛紝閫氳繃涓涓澶存寚閽堟潵鑾峰緱涓涓祫婧愰氬父寰堝ソ錛?
// Example 7: Sources and sinks // // A creator function that builds a new // resource and then hands off ownership. // auto_ptr<T> Source() { return auto_ptr<T>( new T ); } // A disposal function that takes ownership // of an existing resource and frees it. // void Sink( auto_ptr<T> pt ) { } // Sample code to exercise the above: auto_ptr<T> pt( Source() ); // takes ownership
娉ㄦ剰涓嬮潰鐨勫井濡欑殑鍙樺寲錛?
Source()鍒嗛厤浜嗕竴涓柊瀵硅薄騫朵笖浠ヤ竴涓畬鏁村畨鍏ㄧ殑鏂瑰紡灝嗗畠榪斿洖緇欒皟鐢ㄨ咃紝騫惰璋冪敤鑰呮垚涓烘寚閽堢殑鎷ユ湁鐫銆傚嵆浣胯皟鐢ㄨ呭拷鐣ヤ簡榪斿洖鍊鹼紙鏄劇劧錛屽鏋滆皟鐢ㄨ呭拷鐣ヤ簡榪斿洖鍊鹼紝浣犲簲璇ヤ粠鏉ユ病鏈夊啓榪囦唬鐮佹潵鍒犻櫎榪欎釜瀵硅薄錛屽鍚э紵錛夛紝鍒嗛厤鐨勫璞′篃灝嗚鑷姩瀹夊叏鍦板垹闄ゃ?/p>
鍦ㄦ湰鏂囩殑鏈鍚庯紝鎴戝皢婕旂ず榪斿洖涓涓猘uto_ptr鏄竴涓ソ涔犳儻銆傝榪斿洖鍊煎寘瑁硅繘涓浜涗笢瑗挎瘮濡俛uto_ptr閫氬父鏄嬌寰楀嚱鏁板彉寰楀己鍋ョ殑鏈夋晥鏂瑰紡銆?
Sink()閫氳繃浼犲肩殑鏂瑰紡鑾峰緱瀵硅薄鎵鏈夋潈銆傚綋鎵ц瀹孲ink()鐨勬椂鍊欙紝褰撶寮浣滅敤鍩熺殑鏃跺欙紝鍒犻櫎鎿嶄綔灝嗚鎵ц錛堝彧瑕丼ink()娌℃湁灝嗘墍鏈夋潈杞Щ錛夈備笂闈㈡墍鍐欑殑Sink()鍑芥暟瀹為檯涓婂茍娌℃湁瀵瑰弬鏁板仛浠諱綍浜嬫儏錛屽洜姝よ皟鐢ㄢ淪ink(pt);鈥濆氨絳変簬鍐欎簡鈥減t.reset(0);鈥濓紝浣嗘槸澶ч儴鍒嗙殑Sink鍑芥暟閮藉皢鍦ㄩ噴鏀懼畠涔嬪墠鍋氫竴浜涘伐浣溿?
璋ㄨ錛氬崈涓囦笉瑕佷互鎴戜箣鍓嶆病鏈夋彁鍒扮殑鏂瑰紡浣跨敤auto_ptrs銆傛垜宸茬粡鐪嬭榪囧緢澶氱▼搴忓憳璇曠潃鐢ㄥ叾浠栨柟寮忓啓auto_ptrs灝卞儚浠栦滑鍦ㄤ嬌鐢ㄥ叾瀹冨璞′竴鏍楓備絾闂鏄痑uto_ptr騫朵笉鍍忓叾浠栧璞°傝繖閲屾湁浜涘熀鏈師鍒欙紝鎴戝皢鎶婂畠浠彁鍑烘潵浠ュ紩璧蜂綘鐨勬敞鎰忥細
For auto_ptr, copies are NOT equivalent.
褰撲綘璇曠潃鍦ㄤ竴鑸殑浠g爜涓嬌鐢?span style="font-family: 'Courier New'" class="Code">auto_ptrs鐨勬椂鍊欙紝瀹冨皢鎵ц鎷瘋礉錛屽茍涓旀病鏈変換浣曟彁紺猴紝鎷瘋礉鏄笉鐩哥瓑鐨勶紙緇撴灉錛屽畠紜疄灝辨槸鎷瘋礉錛夈傜湅涓嬮潰榪欐浠g爜錛岃繖鏄垜鍦–++鏂伴椈緇勭粡甯哥湅瑙佺殑錛?
// Example 8: Danger, Will Robinson! // vector< auto_ptr<T> > v; /* ... */ sort( v.begin(), v.end() );
鍦ㄦ爣鍑嗗鍣ㄤ腑浣跨敤auto_ptrs鎬繪槸涓嶅畨鍏ㄧ殑銆備竴浜涗漢鍙兘瑕佸憡璇変綘錛屼粬浠殑緙栬瘧鍣ㄦ垨鑰呯被搴撹兘澶熷緢濂藉湴緙栬瘧瀹冧滑錛岃屽彟涓浜涗漢鍒欏憡璇変綘鍦ㄦ煇涓涓祦琛岀殑緙栬瘧鍣ㄧ殑鏂囨。涓湅鍒拌繖涓緥瀛愶紝涓嶈鍚粬浠殑銆?
闂鏄?span style="font-family: 'Courier New'" class="Code">auto_ptr騫朵笉瀹屽叏絎﹀悎涓涓彲浠ユ斁榪涘鍣ㄧ被鍨嬬殑鍓嶆彁錛屽洜涓烘嫹璐?span style="font-family: 'Courier New'" class="Code">auto_ptrs鏄笉絳変環鐨勩傞鍏堬紝娌℃湁浠諱綍涓滆タ璇存槑錛寁ector涓嶈兘鍐沖畾澧炲姞騫跺埗閫犲嚭鈥滄墿灞曗濈殑鍐呴儴鎷瘋礉銆傚啀嬈★紝褰撲綘璋冪敤涓涓竴鑸嚱鏁扮殑鏃跺欙紝瀹冨彲鑳戒細鎷瘋礉鍏冪礌錛屽氨鍍弒ort()閭f牱錛屽嚱鏁板繀欏繪湁鑳藉姏鍋囪鎷瘋礉鏄瓑浠風殑銆傝嚦灝戜竴涓祦琛岀殑鎺掑簭鎷瘋礉鈥滄牳蹇冣濈殑鍏冪礌錛屽鏋滀綘璇曠潃璁╁畠涓?span style="font-family: 'Courier New'" class="Code">auto_ptrs涓璧峰伐浣滅殑璇濓紝瀹冨皢鎷瘋礉涓浠解滄牳蹇冣濈殑auto_ptr瀵硅薄錛堝洜姝よ漿縐繪墍鏈夋潈騫朵笖灝嗘墍鏈夋潈杞Щ緇欎竴涓復鏃跺璞★級錛岀劧鍚庡鍏朵綑鐨勫厓绱犱篃閲囧彇鐩稿悓鐨勬柟寮忥紙浠庣幇鏈夋垚鍛樺垱寤烘洿澶氱殑鎷ユ湁鎵鏈夋潈鐨刟uto_ptr錛夛紝褰撴帓搴忓畬鎴愬悗錛屾牳蹇冨厓绱犲皢琚攢姣侊紝騫朵笖浣犲皢閬囧埌涓涓棶棰橈細榪欑粍搴忓垪閲岃嚦灝戜竴涓猘uto_ptr錛堜篃灝辨槸鍒氭墠琚帀鍖呯殑閭d釜鏍稿績鍏冪礌錛変笉鍐嶆嫢鏈夊璞℃墍鏈夋潈錛岃岄偅涓湡瀹炵殑鎸囬拡宸茬粡闅忕潃涓存椂瀵硅薄鐨勯攢姣佽岃鍒犻櫎浜嗭紒
浜庢槸鏍囧噯濮斿憳浼氬洖閫騫跺笇鏈涘仛涓浜涜兘澶熷府鍔╀綘閬垮厤榪欎簺琛屼負鐨勪簨鎯咃細鏍囧噯鐨刟uto_ptr琚晠鎰忚璁℃垚褰撲綘甯屾湜鍦ㄤ嬌鐢ㄦ爣鍑嗗鍣ㄧ殑鏃跺欎嬌鐢ㄥ畠鏃舵墦鏂綘錛堟垨鑰咃紝鑷沖皯錛屽湪澶ч儴鍒嗙殑鏍囧噯搴撳疄鐜頒腑鎵撴柇浣狅級銆備負浜嗚揪鍒拌繖涓洰鐨勶紝鏍囧噯濮斿憳浼氬埄鐢ㄨ繖鏍蜂竴涓妧宸э細璁?span style="font-family: 'Courier New'" class="Code">auto_ptr's鐨勬嫹璐濇瀯閫犲嚱鏁板拰璧嬪兼搷浣滅鐨勫彸鍊鹼紙rhs錛夋寚鍚戦潪甯擱噺銆傚洜涓烘爣鍑嗗鍣ㄧ殑鍗曞厓绱爄nsert()鍑芥暟錛岄渶瑕佷竴涓父閲忎綔涓哄弬鏁幫紝鍥犳auto_ptrs鍦ㄨ繖閲屽氨涓嶅伐浣滀簡銆傦紙璇戣呮敞錛氬彸鍊間笉鑳借祴鍊肩粰闈炲父閲忥級
灝嗕竴涓猘uto_ptr璁捐鎴?span style="font-family: 'Courier New'" class="Code">const auto_ptrs灝嗕笉鍐嶄涪澶辨墍鏈夋潈錛氭嫹璐濅竴涓猚onst auto_ptr鏄繚娉曠殑錛堣瘧鑰呮敞錛氭病鏈夎繖鏍風殑鏋勯犲嚱鏁幫級錛屽疄闄呬笂浣犲彲浠ラ拡瀵瑰畠鍋氱殑鍞竴浜嬫儏灝辨槸閫氳繃operator*()鎴栬卭perator->()瑙e紩鐢ㄥ畠鎴栬呰皟鐢╣et()鏉ヨ幏寰楁墍鍖呭惈鐨勬寚閽堢殑鍊箋傝繖鎰忓懗鐫鎴戜滑鏈変竴涓畝鍗曟槑浜嗙殑椋庢牸鏉ヨ〃杈句竴涓粷涓嶄涪澶辨墍鏈夋潈鐨刟uto_ptr錛?
// Example 9: The const auto_ptr idiom // const auto_ptr<T> pt1( new T ); // making pt1 const guarantees that pt1 can // never be copied to another auto_ptr, and // so is guaranteed to never lose ownership auto_ptr<T> pt2( pt1 ); // illegal auto_ptr<T> pt3; pt3 = pt1; // illegal pt1.release(); // illegal pt1.reset( new T ); // illegal
榪欏氨鏄垜瑕佽鐨刢osnt錛佸洜姝ゅ鏋滅幇鍦ㄤ綘瑕佸悜涓栫晫璇佹槑浣犵殑auto_ptr鏄笉浼氳鏀瑰彉騫朵笖灝嗘繪槸鍒犻櫎鍏舵墍鏈夋潈錛屽姞涓奵onst灝辨槸浣犺鍋氱殑銆俢onst auto_ptr椋庢牸鏄湁鐢ㄧ殑錛屼綘蹇呴』灝嗗畠璋ㄨ浜庡績銆?
鏈鍚庯紝auto_ptr瀵瑰啓鍑哄紓甯稿畨鍏ㄧ殑浠g爜鏈夋椂鍊欓潪甯稿繀瑕侊紝鎬濊冧笅闈㈢殑浠g爜錛?/p>
// Example 10(a): Exception-safe? // String f() { String result; result = "some value"; cout << "some output"; return result; }
璇ュ嚱鏁版湁涓や釜鍙鐨勪綔鐢細瀹冭緭鍑轟竴浜涘唴瀹癸紝騫朵笖榪斿洖涓涓猄tring銆傚叧浜庡紓甯稿畨鍏ㄧ殑璇︾粏璇存槑瓚呭嚭浜嗘湰鏂囩殑鑼冨洿[2]錛屼絾鏄垜浠兂瑕佸彇寰楃殑鐩爣灝辨槸寮哄紓甯稿畨鍏ㄧ殑淇濋殰錛屽綊緇撲負紜繚鍑芥暟鐨勫師瀛愭р斺斿鏋滄湁寮傚父錛屾墍鏈夌殑浣滅敤涓璧峰彂鐢熸垨鑰呴兘涓嶅彂鐢熴?
铏界劧鍦ㄤ緥10(a)涓殑浠g爜闈炲父綺懼閥錛岀湅璧鋒潵鐩稿綋鎺ヨ繎浜庡紓甯稿畨鍏ㄧ殑浠g爜錛屼絾浠嶇劧鏈変竴浜涘皬鐨勭憰鐤碉紝灝卞儚涓嬮潰鐨勫鎴蜂唬鐮佹墍紺猴細
String theName; theName = f();
鍥犱負緇撴灉閫氳繃鍊艱繑鍥烇紝鍥犳String鐨勬嫹璐濇瀯閫犲嚱鏁板皢琚皟鐢紝鑰屾嫹璐濊祴鍊兼搷浣滅琚皟鐢ㄦ潵灝嗙粨鏋滄嫹璐濆埌theName涓傚鏋滀換浣曚竴涓嫹璐濆け璐ヤ簡錛宖()灝卞畬鎴愪簡鎵鏈夊畠鐨勫伐浣滀互鍙婃墍鏈夊畠鐨勪換鍔★紙榪欏緢濂斤級錛屼絾鏄粨鏋滄槸鏃犳硶鎸藉洖鐨勶紙鍝庡摕鎴戠殑濡堝憖錛?
鎴戜滑鍙互鍋氱殑鏇村ソ鍚楋紝鏄惁鍙互閫氳繃閬垮厤鎷瘋礉鏉ラ伩鍏嶈繖涓棶棰橈紵渚嬪錛屾垜浠彲浠?璁╁嚱鏁版湁涓涓潪甯擱噺寮曠敤鍙傛暟騫跺悜涓嬮潰榪欐牱榪斿洖鍊鹼細
// Example 10(b): Better? // void f( String& result ) { cout << "some output"; result = "some value"; }
榪欑湅璧鋒潵寰堟錛屼絾瀹為檯涓嶆槸榪欐牱鐨勶紝榪斿洖result鐨勮祴鍊肩殑鍑芥暟鍙畬鎴愪簡涓涓姛鑳斤紝鑰屽皢鍏跺畠浜嬫儏鐣欑粰浜嗘垜浠傚畠浠嶇劧浼氬嚭閿欍傚洜姝よ繖涓仛娉曚笉鍙彇銆?
瑙e喅榪欎釜闂鐨勪竴涓柟娉曟槸榪斿洖涓涓寚鍚戝姩鎬佸垎閰嶆寚閽堢殑String瀵硅薄錛屼絾鏄渶濂界殑瑙e喅鏂規鏄鎴戜滑鍋氱殑鏇村錛岃繑鍥炰竴涓寚閽堝寘鍚湪auto_ptr錛?
// Example 10(c): Correct (finally!) // auto_ptr<String> f() { auto_ptr<String> result = new String; *result = "some value"; cout << "some output"; return result; // rely on transfer of ownership; // this can't throw }
榪欓噷鏄竴涓妧宸э紝褰撴垜浠湁鏁堥殣钘忔墍鏈夌殑宸ヤ綔鏉ユ瀯閫犵浜屼釜鍔熻兘錛堣繑鍥炲鹼級褰撶‘淇濆畠鍙互琚畨鍏ㄨ繑鍥炵粰璋冪敤鑰呭茍涓斿湪絎竴涓姛鑳斤紙鎵撳嵃娑堟伅錛夊畬鎴愮殑鏃跺欐病鏈夋姏鍑烘搷浣溿傛垜浠煡閬撲竴鏃out瀹屾垚錛岃繑鍥炲煎皢鎴愬姛浜ゅ埌璋冪敤鑰呮墜涓紝騫朵笖鏃犺濡備綍閮戒細姝g‘娓呯悊錛氬鏋滆皟鐢ㄨ呮帴鍙楄繑鍥炲鹼紝璋冪敤鑰呭皢寰楀埌榪欎釜鎷瘋礉鐨刟uto_ptr涓存椂瀵硅薄鐨勬墍鏈夋潈錛涘鏋滆皟鐢ㄨ呮病鏈夋帴鍙楄繑鍥炲鹼紝涔熷氨鏄拷鐣ヨ繑鍥炲鹼紝鍒嗛厤鐨凷tring灝嗗湪涓存椂auto_ptr琚攢姣佺殑鏃跺欒嚜鍔ㄦ竻鐞嗐傝繖縐嶅畨鍏ㄦ墿灞曠殑浠d環鍛紵灝卞儚鎴戜滑緇忓父瀹炵幇鐨勫己寮傚父瀹夊叏涓鏍鳳紝寮哄畨鍏ㄩ氬父娑堣椾竴浜涙晥鐜囷紙閫氬父姣旇緝灝忥級鈥斺旇繖閲屾寚棰濆鐨勫姩鎬佸唴瀛樺垎閰嶃備絾鏄綋鎴戜滑鍦ㄦ晥鐜囧拰姝g‘鎬т箣闂村仛鍑洪夋嫨鐨勮瘽錛屾垜浠氬父浼氶夋嫨鍚庤咃紒
璁╂垜浠吇鎴愬湪鏃ュ父宸ヤ綔涓嬌鐢╝uto_ptr鐨勪範鎯俛uto_ptr瑙e喅浜嗗父瑙佺殑闂錛屽茍涓旇兘澶熶嬌浣犵殑浠g爜鍙樺緱鏇村畨鍏ㄥ拰鍋ュ.錛岀壒鍒槸瀹冨彲浠ラ槻姝㈠唴瀛樻硠婕忎互鍙婄‘淇濆己瀹夊叏銆傚洜涓哄畠鏄爣鍑嗙殑錛屽洜姝ゅ畠鍦ㄤ笉鍚岀被搴撳拰騫沖彴涔嬮棿鏄彲縐繪鐨勶紝鍥犳鏃犺浣犲湪鍝噷浣跨敤瀹冿紝瀹冮兘灝嗘槸瀵圭殑銆?
This article is drawn from material in the new book Exceptional C++: 47 engineering puzzles, programming problems, and exception-safety solutions by Herb Sutter, 漏 2000 Addison Wesley Longman Inc., which contains further detailed treatments of points touched on briefly in this article, including exception safety, the Pimpl (compiler-firewall) Idiom, optimization, const-correctness, namespaces, and other C++ design and programming topics.
Pimpl椋庢牸鍙互鏈夋晥鍑忓皯欏圭洰鏋勫緩鏃墮棿錛屽洜涓哄畠鍦–縐佹湁閮ㄥ垎鏀瑰彉鐨勬椂鍊欙紝闃繪瀹㈡埛浠g爜寮曡搗騫挎硾鐨勯噸鏂扮紪璇戙傛洿澶氬叧浜嶱impl椋庢牸浠ュ強濡備綍閮ㄧ講緙栬瘧鍣ㄥ錛屽弬鑰冭繖鏈?a href="xc++.htm">Exceptional C++鐨勬潯嬈?6鍒?0銆傦紙Addison-Wesley, 2000錛?
See the article originally published in C++ Report and available on the Effective C++ CD (Scott Meyers, Addison-Wesley, 1999) and Items 8 to 19 in Exceptional C++ (Herb Sutter, Addison-Wesley, 2000).
Type get(int I){ return Type(i); } Type t = get(1);
榪欓噷錛?鎴戜滑浠嶤++鐨勫熀鏈涔夌湅涓婂幓錛?搴旇鏄疶ype(i) 璋冪敤涓嬈℃嫹璐濇瀯閫犲嚱鏁幫紝 鍦ㄥ爢鏍堜腑鐢熸垚涓涓復鏃跺璞★紱鐒跺悗錛岀敤璇ュ璞℃瀯閫犺繑鍥炲璞★紱鐒跺悗瀵硅繖涓復鏃跺璞¤皟鐢ㄦ瀽鏋勫嚱鏁幫紱鍦ㄨ皟鐢ㄨ呮柟錛?鐢ㄨ繑鍥炵殑涓存椂瀵硅薄璋冪敤鎷瘋礉鏋勯犲嚱鏁頒互鍒濆鍖栧璞, 榪斿洖瀵硅薄鐨勬瀽鏋勫嚱鏁板湪榪欎箣鍚庯紝 鍑芥暟榪斿洖涔嬪墠璋冪敤銆?
鎵浠ワ紝 Type t = get(i); 搴旇鏈変笁涓嫹璐濇瀯閫犲嚱鏁板拰涓や釜鏋愭瀯鍑芥暟鐨勮皟鐢?
鍙槸錛?榪樻湁涓縐嶈娉曟槸錛?緙栬瘧鍣ㄥ彲鑳戒細瀵硅繖涓や釜涓存椂瀵硅薄榪涜浼樺寲錛屾渶緇堢殑浼樺寲緇撴灉浼氭槸鍙湁涓嬈$殑鏋勯犲嚱鏁般傚洜涓哄緢鏄庢樉鍦板彲浠ョ湅鍒幫紝 榪欓噷鎴戜滑鍏跺疄鍙槸瑕佺敤涓涓暣鏁版瀯閫犱竴涓猅ype瀵硅薄銆?
鍡? 浼間箮寰堟湁閬撶悊錛?
閭d箞錛?鍝竴縐嶈娉曞鍛紵 娌℃湁璋冩煡灝辨病鏈夊彂璦鏉冿紝浜庢槸鏈漢鐢╒C++6.0鍋氫簡瀹為獙銆?鏀句簡浜沜out<<鈥?.鍦ㄦ嫹璐濇瀯閫犲嚱鏁伴噷錛岃瀵熸墦鍗扮殑緇撴灉錛?緇撴灉鍗存槸璺熸垜鐨剆imple, na茂ve鐨勯嫻嬩竴鑷淬備笁涓嫹璐濇瀯閫犲嚱鏁幫紝 涓や釜鏋愭瀯鍑芥暟銆?
鈥滀綘涓急鏅虹紪璇戝櫒錛佽剳琚嬭繘姘翠簡鍚э紵鈥?蹇樹簡緙栬瘧鍣ㄦ病鑴戣浜?鈥滃緢鏄庢樉鍦ㄨ繖涓緥瀛愰噷鎴戠殑涓や釜涓存椂瀵硅薄閮芥病鏈夌敤鐨勫晩錛佲?
浜庢槸錛屼笂緗戯紝 鏌ヨ祫鏂欙紝 google涓涓嬪惂錛?
涓嬮潰鏄垜鏌ュ埌鐨勪竴浜涚粨鏋滐細
鍏跺疄錛?榪欑瀵瑰間紶閫掔殑浼樺寲鐨勭爺絀訛紝 騫朵笉鍙眬闄愪簬榪斿洖鍊箋傚涓嬮潰榪欎釜渚嬪瓙錛?
void f(T t) { } void main(void){ T t1; f(t1); }
涔熸湁榪欑鑰冭檻銆?
f(T)鏄寜鍊間紶閫掔殑銆傝涔変笂搴旇鍋氫竴涓鍒訛紝 浣垮緱鍑芥暟鍐呴儴瀵筎鐨勬敼鍙樹笉浼氬獎鍝嶅埌鍘熸潵鐨則1.
浣嗘槸錛屽洜涓哄湪璋冪敤f(t1)涔嬪悗錛?鎴戜滑娌℃湁鍐嶄嬌鐢╰1(闄や簡涓涓殣鍚殑destructor璋冪敤)錛屾槸鍚﹀彲鑳芥妸澶嶅埗浼樺寲鎺夛紝 鐩存帴浣跨敤t1鍛紵榪欐牱鍙互鑺傜渷鎺変竴涓嫹璐濇瀯閫犲嚱鏁板拰涓涓瀽鏋勫嚱鏁般?
鍙槸錛?涓嶈鏄榪斿洖鍊肩殑浼樺寲錛?榪樻槸瀵逛笂闈㈣繖縐嶅眬閮ㄥ璞$殑浼樺寲錛屽湪1995騫寸殑C++鏂版爣鍑嗚崏妗堝嚭鍙板墠閮芥槸涓烘爣鍑嗘墍涓ユ牸闄愬埗鐨?(铏界劧鏈変簺緙栬瘧鍣ㄥ茍娌℃湁閬佃榪欎釜鏍囧噯錛?榪樻槸鏀寔浜嗚繖縐嶁滀紭鍖栤?
閭d箞錛?榪欏張鏄負浠涔堝憿錛?
榪欓噷闈㈡秹鍙婂埌涓涓櫘閬嶇殑瀵箂ide-effect鐨勬媴蹇с?
浠涔堝張鏄痵ide-effect鍛紵
鎵璋搒ide-effect灝辨槸涓涓嚱鏁扮殑璋冪敤涓庡惁鑳藉瀵圭郴緇熺殑鐘舵侀犳垚鍖哄埆銆?
int add(int i, int j){ return i+j; }灝辨槸娌℃湁side-effect鐨勶紝鑰?
void set(int* p, int I, int v){ p[I]=v; }灝辨槸鏈塻ide-effect鐨勩傚洜涓哄畠鏀瑰彉浜嗕竴涓暟緇勫厓绱犵殑鍊鹼紝 鑰岃繖涓暟緇勫厓绱犲湪鍑芥暟澶栨槸鍙鐨勩?
閫氬父鎰忎箟涓婃潵璇達紝 鎵鏈夌殑浼樺寲搴旇鍦ㄤ笉褰卞搷紼嬪簭鐨勫彲瑙傚療琛屼負鐨勫熀紜涓婅繘琛岀殑銆傚惁鍒欙紝蹇垯蹇簡錛?緇撴灉鍗村拰鎵鎯寵鐨勫畬鍏ㄤ笉鍚岋紒
鑰孋++鐨勬嫹璐濇瀯閫犲嚱鏁板拰鏋愭瀯鍑芥暟鍙堝緢澶氶兘鏄湁side-effect鐨勩傚鏋滄垜浠殑鈥滀紭鍖栤濆幓鎺変簡涓涓湁side-effect鐨勬嫹璐濇瀯閫犲嚱鏁板拰涓涓瀽鏋勫嚱鏁幫紝 榪欎釜鈥滀紭鍖栤濆氨鏈夊彲鑳芥敼鍙樼▼搴忕殑鍙瀵熻涓恒傦紙娉ㄦ剰錛?鎴戣繖閲岃鐨勬槸鈥滃彲鑳解濓紝鍥犱負鈥滆礋璐熷緱姝b濓紝 涓や釜鏈塻ide-effect鐨勫嚱鏁扮殑璋冪敤錛?鍦ㄤ笉鑰冭檻騫惰榪愯鐨勬儏鍐典笅錛?涔熻鍙嶈屼笉浼氬獎鍝嶇▼搴忕殑鍙瀵熻涓恒備笉榪囷紝 榪欑濉炵縼澶遍┈鐨勪簨鍎匡紝 緙栬瘧鍣ㄥ氨寰堥毦鍒ゆ柇浜嗭級
鍩轟簬榪欑蹇ц檻, 1995騫翠互鍓嶇殑鏍囧噯錛?鏄庣‘紱佹瀵瑰惈鏈塻ide-effect鐨勬嫹璐濇瀯閫犲嚱鏁板拰鏋愭瀯鍑芥暟鐨勪紭鍖栥傚悓鏃訛紝 榪樻湁涓浜涘C++鎵╁厖鐨勬彁璁紝 鑰冭檻璁╃▼搴忓憳鑷繁瀵圭被榪涜鍏佽浼樺寲鐨勫0鏄庛?紼嬪簭鍛樺彲浠ユ槑紜湴鍛婅瘔緙栬瘧鍣細涓嶉敊錛?鎴戣繖涓嫹璐濇瀯閫犲嚱鏁幫紝 鏋愭瀯鍑芥暟鏄湁side-effect, 浣嗕綘鍒錛?灝界浼樺寲錛?鍑轟簡浜嬫湁鎴戝憿錛?
鍝庯紝 side-effect鐪熸槸涓涓浜哄張鎭ㄥ張鐖辯殑涓滆タ錛佸畠浣跨紪璇戝櫒鐨勪紭鍖栧彉寰楀洶闅撅紱鍔犲ぇ浜嗙▼搴忕淮鎶ゅ拰璋冭瘯鐨勯毦搴︺傚洜姝?functional language 鎶妔ide-effect褰撲綔媧按鐚涘吔涓鏍鳳紝騫茶剢紱佹銆備絾鍚屾椂錛屾垜浠張寰堥毦紱誨紑side-effect. 涓嶈紼嬪簭鍛樹滑鏇翠範鎯簬imperative 鐨勭紪紼嬫柟娉? 璞℃暟鎹簱鎿嶄綔錛孖O鎿嶄綔閮藉ぉ鐒跺氨鏄痵ide-effect.
涓嶈繃錛屼釜浜鴻繕鏄涓篊++鏍囧噯瀵光滀紭鍖栤濈殑淇濆畧鎬佸害鏄湁閬撶悊鐨勩傛棤璁哄浣曪紝璁┾滀紭鍖栤濆彲浠ユ綔鍦ㄥ湴鍋峰伔鍦版敼鍙樼▼搴忕殑琛屼負鎬繪槸璁╀漢鎯寵搗鏉ュ氨涓嶈垝鏈嶇殑銆?
浣嗘槸錛?鐭涚浘鏄绔嬬粺涓鐨勩傦紙鎯沖綋騫翠亢椹垪鍙緱浜嗗叓鍗佸鍒嗗憿錛夈?瀵硅繖縐峚ggressive鐨勨滀紭鍖栤濈殑鍛煎0鏄竴嫻珮榪囦竴嫻?浠tan Lippeman涓洪鐨勪竴灝忔挳欏藉浐鍒嗗瓙瀵規爣鍑嗙殑棰犺鍜屽拰騫蟲紨鍙樼殑闃磋皨浠庢潵灝辨病鏈夊仠姝㈣繃銆?榪欎笉錛熷湪1996騫寸殑涓涓闆ㄤ氦鍔犵殑澶滄櫄錛?涓涓槾闄╃殑C++鏂版爣鍑嗚崏妗堝嚭鐐変簡銆傚湪榪欎釜鑽夋閲岋紝 鍔犲叆浜嗕竴涓悕涓篟VO (Return Value Optimization) 鐨勬斁瀹藉浼樺寲鐨勯檺鍒訛紝 濡勫浘璧拌祫鏈富涔夐亾璺紝 緇欒祫鏈寮犵洰鐨勬彁妗堛傚叾鍏蜂綋鍐呭灝辨槸璇達細鍏佽緙栬瘧鍣ㄥ鍛藉悕榪囩殑灞閮ㄥ璞$殑榪斿洖榪涜浼樺寲錛?鍗充嬌鎷瘋礉鏋勯犲嚱鏁?鏋愭瀯鍑芥暟鏈塻ide-effect涔熷湪鎵涓嶆儨銆傝繖涓彁璁儗鍚庢墍闅愯棌鐨勬濇兂灝辨槸錛氫負浜嗘彁楂樻晥鐜囷紝 瀹佸彲鍐掓敼鍙樼▼搴忚涓虹殑椋庨櫓銆傚畞瑕佽祫鏈富涔夌殑鑻楋紝 涓嶈紺句細涓諱箟鐨勮崏浜嗭紒
鎴戞兂錛?榪欐牱鐨勪竴涓姜澶ф伓鏋佺殑鎻愭绔熶細琚彁浜わ紝搴旇鏄洜涓篊++鐨勫兼嫹璐濈殑璇箟鐨勬晥鐜囧疄鍦ㄥお鈥滃濡堢殑鈥濅簡銆?褰撲綘鍐欎竴涓?Complex operator+(const Complex& c1, const Complex& c2);鐨勬椂鍊欙紝 绔熼渶瑕佽皟鐢ㄥソ鍑犳鎷瘋礉鏋勯犲嚱鏁板拰鏋愭瀯鍑芥暟錛佸悓蹇椾滑錛侊紙娌夌棝鍦幫紝 璇噸蹇冮暱鍦幫級紺句細涓諱箟鐨勭敓浜у叧緋葷殑浼樿秺鎬ф庝箞浣撶幇鍟婏紵
鎺ヤ笅鏉ワ紝 褰撴垜鎯矴oogle C++鏈鏂扮殑鏍囧噯錛?鐪婻VO鏄惁琚渶緇堥噰綰蟲椂錛?鍗翠粈涔堜篃鎵句笉鍒頒簡銆?鍒癆NSI鐨勭綉绔欎笂鍘伙紝 灞呯劧瑕佷粯閽辨墠鑳紻OWNLOAD鏂囨。銆?鈥滆佸瓙鍦ㄥ煄閲屼笅棣嗗瓙閮戒笉浠橀挶錛?down浣犲嚑涓儌鏂囨。榪樿緇欓挶錛燂紒鈥?
鏁呬簨娌℃湁緇撳眬錛?瀹炲湪鏄笉鐖姐?涔熶笉鐭ユ槸涓嶆槸鍥犱負鏍囧噯榪樻病鏈夋暡瀹氾紝 鎵浠C++6 灝辨病鏈変紭鍖栵紝 榪樻槸VC鏍規湰灝辨病瀹屽叏閬靛畧鏍囧噯銆?
涓嶈繃錛屾湁涓鐐規槸鑲畾鐨勩?褰撳啓紼嬪簭鐨勬椂鍊欙紝 鏈濂戒笉瑕佷緷璧栦簬RVO (鏈変漢錛?璞tan Lippeman, 鍙堝彨瀹僋RV浼樺寲)銆?鍥犱負錛?涓嶈瀵規爣鍑嗙殑浜夎鏄惁宸茬粡鏈変簡緇撴灉錛?瀹為檯涓婂悇涓紪璇戝櫒鐨勫疄鐜頒粛榪樻槸鍚勮嚜涓烘斂錛?娌℃湁緇熶竴銆?涓涓彨SCOtt Meyers鐨勫浼?蹇樹簡鏄崠浠涔堢殑浜?灝辮錛?濡傛灉浣犵殑紼嬪簭渚濊禆浜嶳VO, 鏈濂藉幓鎺夎繖縐嶄緷璧栥備篃灝辨槸璇達紝 涓嶇RVO鍒板簳鏍囧噯涓嶆爣鍑嗭紝 浣犺繕鏄笉鑳界敤銆?涓嶄粎涓嶈兘鐢紝 榪樺緱鏃跺埢璀︽儠鐫RVO鍙兘甯︽潵鐨勭▼搴忚涓轟笂鐨勫彉鍖栥?錛堜篃涓嶇煡榪欏府瀹朵紮鐬庡繖浜嗗崐澶╁埌搴曚負鍟ワ紒錛?
璇村埌榪欓噷錛?鍊掓兂璧蜂簡C#閲屼竴涓洶鎯戜簡鎴戝緢涔呯殑闂銆傝寰楄C#鐨剆pecification鐨勬椂鍊欙紝 闈炲父涓嶈В涓轟粈涔圕#涓嶅厑璁哥粰value type 瀹氫箟鏋愭瀯鍑芥暟銆?
榪欓噷錛?鍏堢畝鐣ヤ粙緇嶄竴涓婥#閲岀殑value type (鍘熷鏁版嵁綾誨瀷錛?struct 綾誨瀷)銆?
鍦–#閲岀殑value_type灝辮薄鏄鹼紝 姘歌繙鍙兘copy, 鍙栧箋傚洜姝わ紝 瀹冩案榪滄槸in-place鐨勩傚鏋滀綘鎶婁竴涓獀alue type鐨勬暟鎹斁鍦ㄤ竴涓璞¢噷錛屽畠鐨勭敓鍛芥湡灝卞拰閭d釜瀵硅薄鐩稿悓錛涘鏋滀綘澹版槑涓涓獀alue type 鐨勫彉閲忓湪鍑芥暟涓紝 瀹冪殑鐢熷懡鏈熷氨鍦╨exical scope閲屻?
{
The_ValueType value;
}//value 鍒拌繖閲屽氨姝昏彍浜?
鍟婂憖鍛錛?榪欎笉姝f槸鎴戜滑鎬蹇電殑C++鐨剆tack object鍚楋紵
鍦–++閲岋紝Auto_ptr, shared_ptr, 瀹瑰櫒浠紝 涓嶉兘鏄埄鐢ㄦ瀽鏋勫嚱鏁版潵綆$悊璧勬簮鐨勫悧錛?
C#錛孞ava 铏界劧鍒╃敤garbage collection鎶鏈潵鏀墮泦鏃犵敤瀵硅薄錛?浣挎垜浠笉鐢ㄥ啀鎷呭績鍐呭瓨鐨勫洖鏀躲?浣唃arbage collection騫朵笉淇濊瘉鏃犵敤瀵硅薄涓瀹氳鏀墮泦錛?騫朵笉淇濊瘉Dispose()鍑芥暟涓瀹氳璋冪敤錛?鏇翠笉淇濊瘉涓涓璞′粈涔堟椂鍊欒鍥炴敹銆?鎵浠ュ涓浜涢潪鍐呭瓨鐨勮祫婧愶紝 璞℃暟鎹簱榪炴帴錛?緗戠粶榪炴帴錛?鎴戜滑榪樻槸甯屾湜鑳芥湁涓涓被浼間簬smart pointer鐨勪笢瑗挎潵甯垜浠鐞嗗晩銆傦紙try-finally 铏界劧鍙互鐢紝 浣嗗洜涓哄畠褰卞搷鍒發exical scope, 鏈夋椂鐢ㄨ搗鏉ヤ笉閭d箞鏂逛究錛?
浜庢槸錛?鎴戝C#鐨勫彇娑坴alue type鐨勬瀽鏋勫嚱鏁板厖婊′簡娣卞帤鐨勯樁綰т粐鎭ㄣ?
涓嶈繃錛?鐜板湪鎯蟲潵錛?C#鐨勮繖縐嶈璁′竴瀹氭槸鎯╀簬C++澶辮觸鐨勬暀璁細
1. value type 娌℃湁鎷瘋礉鏋勯犲嚱鏁般侰#鍙仛緙虹渷copy, 娌℃湁side-effect
2. value type 涓嶅噯鏈夋瀽鏋勫嚱鏁般侰#鏈塯arbage collection, 鏋愭瀯鍑芥暟鐨勫敮涓鐢ㄩ斿彧浼氭槸鍋氫竴浜泂ide-effect璞″叧闂暟鎹簱榪炴帴銆?鎵浠ュ彇娑堜簡鏋愭瀯鍑芥暟錛?灝卞彇娑堜簡value type鐨剆ide-effect.
3. 娌℃湁浜唖ide-effect, 緋葷粺鍙互浠繪剰鍦板仛浼樺寲浜?
瀵逛互涓嬬▼搴忥細
The_Valuetype get(int I){return The_Valuetype(i);}
The_Valuetype t = get(1);
鍦–#閲屾垜浠彲浠ュ揩涔愬湴璇達細鍙皟鐢ㄤ簡涓嬈℃瀯閫犲嚱鏁般?鍐嶆病鏈塻ide-effect鐨勬矙婕狅紝 鍐嶆病鏈夐毦浠ヤ紭鍖栫殑鑽掑師錛?smart pointer鏈涜屽嵈姝ワ紝 鏁堢巼涔嬭姳澶勫寮閬嶃?I have a dream, 鈥︹?/p>
杞澆鑷細http://gugu99.itpub.net/post/34143/466008
浜庢槸灝辨湁浜嗕笅闈㈢殑鍋氭硶錛屽簲璇ヤ笉闅劇悊瑙o細
template<class T> class smart_ptr { public: smart_ptr(T* t = 0) { real_ptr = t; } ~smart_ptr() { delete real_ptr; } T* operator ->() const { return real_ptr; } T& operator *() const { return *real_ptr; } private: T* real_ptr; };
鎴戜滑甯屾湜鎴戜滑鐨勬櫤鑳芥寚閽堣兘澶熷儚鎸囬拡涓鏍峰湴宸ヤ綔錛屼絾涓嬮潰鐨勫伐浣滄柟寮忎技涔庡瓨鍦ㄩ棶棰橈細
鍦ㄦ櫘閫氱殑dumb鎸囬拡涓紝浠ヤ笅琛屼負鏄紜殑錛?pre class="gc-code">void letUsGo(BaseClass* objPtr); DerivedClass* derivedObjPtr2 = new DerivedClass(); letUsGo(derivedObjPtr2); delete derivedObjPtr2;
浣嗘槸錛屼互涓嬩唬鐮佸憿錛?pre class="gc-code">void letUsSmartGo(const smart_ptr<BaseClass>& objPtr); smart_ptr<DerivedClass> smartDerivedObjPtr2(new DerivedClass()); // the smart_ptr<DerivedClass> is not inherited from the smart_ptr<BaseClass> // the compiler can't find the class to cast it, so it must cause the error. letUsSmartGo(smartDerivedObjPtr2);
涓嬮潰鐨勮繃紼嬫弿榪頒簡榪欎釜鍙樺寲鎵闇瑕佺殑涓浜涙敮鎸侊細
1銆乪rror C2664: 鈥渓etUsSmartGo鈥? 涓嶈兘灝嗗弬鏁?1 浠庘渟mart_ptr<T>鈥濊漿鎹負鈥渃onst smart_ptr<T> &鈥?br>2銆乻martDerivedObjPtr2鐨勭被鍨嬶細
smart_ptr<DerivedClass> smartDerivedObjPtr2(new DerivedClass());
3銆乴etUsSmartGo鐨勫0鏄庯細
void letUsSmartGo(const smart_ptr<BaseClass>&);
4銆侀棶棰樿漿鍖栦負錛屽浣曚粠smart_ptr<DerivedClass>鍒癱onst smart_ptr<BaseClass>&鐨勮漿鍙樸?br>5銆侀拡瀵筶etUsSmartGo鐨勫0鏄庯紝鍙互鏈夌殑瀹炲弬綾誨瀷鍖呮嫭錛?br> const smart_ptr<BaseClass>
smart_ptr<BaseClass>
鍋囪瀛樺湪浠ヤ笅綾誨瀷 smart_derived_ptr : smart_ptr<BaseClass>錛岄偅涔坰mart_derived_ptr涔熸槸鍙互琚紶閫掔殑銆?br>6銆佽繖閲屽瓨鍦ㄨ繖鏍蜂竴涓棶棰橈細
new DerivedClass() 琚紶閫掔粰smartDerivedObjPtr2涔嬪悗錛宻martDerivedObjPtr2灝辨嫢鏈変簡瀹冪殑鎸囬拡銆傚鏋滀粠smartDerivedObjPtr2闅愬紡杞崲鎴愬彟涓涓猻mart_ptr<X>鍚庯紝鎴戜滑闇瑕佽В鍐崇殑灝辨槸灝唖martDerivedObjPtr2鎵鎷ユ湁鐨勬寚閽堜紶閫掔粰smart_ptr<X>騫跺皢smartDerivedObjPtr2鐨勫唴閮ㄦ寚閽堟竻闆訛紙榪欐牱灝變笉浼氬湪smartDerivedObjPtr2琚攢姣佺殑鏃跺欙紝鍥犱負璋冪敤delete real_ptr錛岃屽畠鐨勬柊鎷瘋礉鍦ㄧ寮浣滅敤鍩熺殑鏃跺欙紝涓鏍蜂細鍐嶆璋冪敤delete real_ptr錛岃屾鏃秗eal_ptr鎸囧悜鐨勫璞″凡緇忚閲婃斁錛屽洜姝よ繖鏍風殑琛屼負鏄湭瀹氫箟鐨勩傦級
7銆佸洜姝わ紝瀹氫箟濡備笅鏂規硶鍗沖彲錛?pre class="gc-code">template<class T>
class smart_ptr {
public:
smart_ptr(T* t = 0) {
std::cout << "creating smart_ptr ...smart_ptr(T* t = 0)" << std::endl;
real_ptr = t;
}
template<class U>
smart_ptr(smart_ptr<U>& rhs) : real_ptr(rhs.real_ptr){
std::cout << "creating smart_ptr ...smart_ptr(smart_ptr<U>& rhs)" << std::endl;
rhs.real_ptr = 0;
}
~smart_ptr() {
std::cout << "destoring smart_ptr ..." << std::endl;
delete real_ptr;
}
T* operator ->() const { return real_ptr; }
T& operator *() const { return *real_ptr; }
T* real_ptr;
};
8銆佷絾鏄繖閲宺eal_ptr鎸夌収涔犳儻搴旇鏄竴涓鏈夋垚鍛橈紝鑰屼笖鎴戜滑鍦ㄥ畬鎴愯鏂規硶鏃跺欙紝甯屾湜鑳藉瀹炵幇涓縐嶆墍璋撶殑鎵鏈夋潈杞Щ錛屼篃灝辨槸灝嗗唴閮ㄧ殑鎸囬拡浼犻掔粰鍙︿竴涓櫤鑳芥寚閽堬紝鑰岃繖搴旇鏄竴涓師瀛愯繃紼嬨傚洜姝わ紝鎴戜滑瀹炵幇浠ヤ笅鏂規硶錛?/p>
template<class T> class smart_ptr { public: smart_ptr(T* t = 0) { std::cout << "creating smart_ptr ...smart_ptr(T* t = 0)" << std::endl; real_ptr = t; } template<class U> smart_ptr(smart_ptr<U>& rhs) : real_ptr(rhs.release()){ std::cout << "creating smart_ptr ...smart_ptr(smart_ptr<U>& rhs)" << std::endl; } ~smart_ptr() { std::cout << "destoring smart_ptr ..." << std::endl; delete real_ptr; } T* operator ->() const { return real_ptr; } T& operator *() const { return *real_ptr; } // helper T* release() { T* tmp = real_ptr; real_ptr = 0; return tmp; } private: T* real_ptr; };
1銆佽緗滅敓鎴愭椂鍚敤C/C++浠g爜鍒嗘瀽鈥濅負鈥滄槸鈥濓紝濡傛灉涓嶈緗欏癸紝紼嬪簭閫熷害灝嗗嚭涔庝綘鐨勬剰鏂欌︹?/p>
2銆佺偣鍑燴滃垎鏋愨?>鈥滃惎鍔ㄦц兘鍚戝鈥?/p>
3銆佸湪鈥滄ц兘璧勬簮綆$悊鍣ㄢ濅腑鍙抽敭鏂板緩鐨勬ц兘鎶ュ憡鑺傜偣錛屽彸閿滃惎鍔ㄥ茍鍚敤鍒嗘瀽鍔熻兘鈥濄?/p>
铏界劧姝ゅ鏈夆滃惎鐢ㄥ垎鏋愬姛鑳解濓紝浣嗗鏋滃湪閰嶇疆閲岄潰娌℃湁榪涜璁劇疆錛岀涓嬈$殑嫻嬭瘯鎶ュ憡緇撴灉灝嗘槸涓嶅噯紜殑銆?/p>
4銆侀夋嫨涓や釜鎬ц兘鎶ュ憡錛坈trl+榧犳爣錛夛紝鍙抽敭鈥滄瘮杈冩ц兘鎶ュ憡鈥濄?/p>
鐢ㄦц兘鎶ュ憡灝嗘湁鍔╀簬鎻愰珮紼嬪簭鐨勬ц兘錛屽茍涓斿揩閫熷畾浣嶉棶棰樻墍鍦紝鍓╀笅鐨勭粨鏋滃氨鏄綘鑷繁闇瑕佸瑙傚療錛屽垎鏋愭ц兘鎶ュ憡鎵鍙嶆槧鐨勯棶棰樹簡銆?br>
鏇村
VC++ 6.0璇﹁榪欓噷>> http://neural.cs.nthu.edu.tw/jang/mir/technicalDocument/vc6_profile/index.htm
絎笁鏂瑰伐鍏?gt;> http://www.semdesigns.com/Products/Profilers/CppProfiler.html
/* * single_argument_ctor.cpp * * Created on: 2010-3-29 * Author: Volnet * Compiler: GNU C++(version 3.4.5) * MSVC CL(version 15.00.30729.01) */ #include <stdlib.h> #include <iostream> #include <sstream> // single-argument class class SingleArgumentClass { private: int _inner; public: SingleArgumentClass() :_inner(-1) { } SingleArgumentClass(int actual) :_inner(actual) { } bool operator==(const SingleArgumentClass& rhs); std::string str(){ // we'd better to use boost::lexical_cast to cast. // #region cast std::stringstream strStream; strStream << _inner; std::string str; strStream >> str; // #endregion return str; } }; bool SingleArgumentClass::operator ==(const SingleArgumentClass& rhs){ if(_inner == rhs._inner) return true; return false; } // single-argument class fixed bug by explicit keyword. class SingleArgumentClassFixedBugByExplicitKeyword { private: int _inner; public: SingleArgumentClassFixedBugByExplicitKeyword() :_inner(-1) { } explicit SingleArgumentClassFixedBugByExplicitKeyword(int actual) :_inner(actual) { } bool operator==(const SingleArgumentClassFixedBugByExplicitKeyword& rhs); std::string str(){ // we'd better to use boost::lexical_cast to cast. // #region cast std::stringstream strStream; strStream << _inner; std::string str; strStream >> str; // #endregion return str; } }; bool SingleArgumentClassFixedBugByExplicitKeyword::operator ==(const SingleArgumentClassFixedBugByExplicitKeyword& rhs){ if(_inner == rhs._inner) return true; return false; } // single-argument class fixed bug by helper class. class ActualType { public: ActualType(int value):_value(value){}; int get_value(){ return _value; } private: int _value; }; class SingleArgumentClassFixedBugByHelperClass { private: int _inner; public: SingleArgumentClassFixedBugByHelperClass() :_inner(-1) { } SingleArgumentClassFixedBugByHelperClass(ActualType actual) :_inner(actual.get_value()) { } bool operator==(const SingleArgumentClassFixedBugByHelperClass& rhs); std::string str(){ // we'd better to use boost::lexical_cast to cast. // #region cast std::stringstream strStream; strStream << _inner; std::string str; strStream >> str; // #endregion return str; } }; bool SingleArgumentClassFixedBugByHelperClass::operator ==(const SingleArgumentClassFixedBugByHelperClass& rhs){ if(_inner == rhs._inner) return true; return false; } void Assert(bool status, std::string strTrue = std::string("assert result is true;"), std::string strFalse = std::string("assert result is false;")); int main(void){ SingleArgumentClass obj(3); std::cout << obj.str() << std::endl; // our purpose. SingleArgumentClass obj1(1); SingleArgumentClass obj2(1); Assert(obj1 == obj2, "obj1 == obj2", "obj1 != obj2"); int i = 3; // warning!!! // obj is a SingleArgumentClass object. // i is a integer. // operator== only define the equal between two SingleArgumentClass object. // In fact: // obj == i: // 1.compiler found the operator== require two SingleArgumentClass object. // 2.compiler try to find a cast method for casting int to SingleArgumentClass. // 3.compiler found it can use the SingleArguementClass.Ctor(int) // to create a new SingleArgumentClass. // 4.compiler try to create a new SingleArgumentClass object from i. // 5.so it without any warning and error, but it's logical not we need. Assert(obj == i, "obj == i //right?", "obj != i"); // Assert(i == obj); // Compile ERROR: no match for 'operator==' in 'i == obj' // it's may encounter a compile-time error. // GNU G++: no match for 'operator==' in 'objFixed == i' single_argument_ctor.cpp single_argument_ctor/src 106 C/C++ Problem // MSVC: 閿欒 1 error C2679: 浜岃繘鍒垛?=鈥? 娌℃湁鎵懼埌鎺ュ彈鈥渋nt鈥濈被鍨嬬殑鍙蟲搷浣滄暟鐨勮繍綆楃(鎴栨病鏈夊彲鎺ュ彈鐨勮漿鎹? {projectpath}\single_argument_ctor\src\single_argument_ctor.cpp 107 single_argument_ctor SingleArgumentClassFixedBugByExplicitKeyword objFixed(3); // Assert(objFixed == i, "objFixed == i", "objFixed != i"); SingleArgumentClassFixedBugByHelperClass objFixedByHelper1(3); SingleArgumentClassFixedBugByHelperClass objFixedByHelper2(3); // it's may encounter a compile-time error. // GNU G++: no match for 'operator==' in 'objFixedAuto1 == i' single_argument_ctor.cpp single_argument_ctor/src 158 C/C++ Problem // MSVC: 閿欒 1 error C2679: 浜岃繘鍒垛?=鈥? 娌℃湁鎵懼埌鎺ュ彈鈥渋nt鈥濈被鍨嬬殑鍙蟲搷浣滄暟鐨勮繍綆楃(鎴栨病鏈夊彲鎺ュ彈鐨勮漿鎹? {projectpath}\single_argument_ctor\src\single_argument_ctor.cpp 163 single_argument_ctor // Assert(objFixedByHelper1 == i); } void Assert(bool status, std::string strTrue, std::string strFalse) { std::cout << (status strTrue : strFalse) << std::endl; }
瑙e喅鏂規硶錛?/p>
1銆乪xplicit鍏抽敭瀛楋紝鍦ㄥ崟鍙傛暟鏋勯犲嚱鏁板墠浣跨敤explicit鍙傛暟錛屽彲浠ラ伩鍏嶅崟鍙傛暟鏋勯犲嚱鏁拌鐢ㄤ簬闅愬紡杞崲銆?/p>
2銆佸埄鐢ㄤ腑闂寸被鐨勬柟寮忥紝璇﹁浠g爜鈥淪ingleArgumentClassFixedBugByHelperClass鐩稿叧閮ㄥ垎鈥濄傚鏋滅紪璇戝櫒涓嶆敮鎸佽В鍐蟲柟娉?錛屽垯寤鴻浣跨敤姝ゆ柟娉曘備笂闈唬鐮佹墍鎻愬強鐨勪袱嬈句富嫻佺紪璇戝櫒鍧囨敮鎸乪xplicit鍏抽敭瀛椼?/p>
鏈夋椂鍊欐垜浠彲浠ョ敤namespace鏉ョ粍緇囧懡鍚嶇┖闂淬?/p>
鏈夋椂鍊欐垜浠張甯屾湜灝嗕竴浜涜緝娣卞眰嬈$殑綾誨彉鎴愭垜浠瘮杈冨鏄撹闂殑瀵硅薄銆?/p>
涓嬮潰鐨勪唬鐮佹彁渚涗簡涓縐嶇畝鍗曠殑紺轟緥鏉ユ弧瓚寵繖鏍風殑闇姹傘?/p>
1銆佺敤namespace鏉ョ粍緇囧悇涓被鐨勫眰綰у叧緋匯?/p>
2銆佺敤using鍏抽敭瀛楋紝灝嗘繁灞傛緇撴瀯鏆撮湶鍒拌緝澶栧眰銆?/p>
//============================================================================ // Name : namespace.cpp // Author : Volnet // Version : // Copyright : reserve by volnet@tom.com // Description : namespace in C++, Ansi-style //============================================================================ #include <iostream> namespace volnet { namespace extensions { class _Console { public: void WriteLine(std::string); }; } using extensions::_Console; } using namespace volnet; _Console Console; void _Console::WriteLine(std::string s) { std::cout << s << std::endl; } using namespace std; int main() { Console.WriteLine(std::string("I'm volnet!")); return 0; }
boost::tuple<derived> tup4; boost::tuple<base> tup5; tup5 = tup4; tup4.get<0>().test(); tup5.get<0>().test(); // 涓㈠け澶氭佹?br> derived d; boost::tuple<derived*> tup6(&d); boost::tuple<base*> tup7; tup7 = tup6; tup6.get<0>()->test(); tup7.get<0>()->test(); // 鎭㈠澶氭佹э紙鏂規硶1錛? boost::tuple<derived&> tup8(d); boost::tuple<base&> tup9(tup8);
// tup9 = tup8; 涓嶈兘浣跨敤璇ユ柟娉曪紝鍥犱負鏃犳硶瀵瑰紩鐢ㄨ祴鍊箋? tup8.get<0>().test(); tup9.get<0>().test(); // 鎭㈠澶氭佹э紙鏂規硶2錛?/span>
/* * tuple.cpp * * Created on: 2010-3-25 * Author: GoCool */ #include <stdlib.h> #include <iostream> #include <boost/tuple/tuple.hpp> #include <boost/tuple/tuple_io.hpp> #include "../header/baseClass.h" using namespace std; class X { X(); public: X(std::string){} }; class Y { Y(const Y&); public: Y(){} }; class A { }; bool operator==(A, A) { std::cout << "All the same to me..."; return true; } void f(int i); void cut_off_rule(void); int main(void){ // add a new tuple boost::tuple<int,double,std::string> triple(42, 3.14, "My first tuple!"); int a = triple.get<0>(); ++a; cout << a << endl; cout << triple << endl; cut_off_rule(); boost::tuple<int, double> pair = boost::make_tuple(21, 22.5); cout << pair << endl; cut_off_rule(); int pair_element_1 = -1; double pair_element_2 = -1; boost::tie(pair_element_1, pair_element_2) = pair; cout << pair_element_1 << "," << pair_element_2 << endl; cut_off_rule(); boost::tuple<int,std::string,derived> tup1(-5,"Tuples"); boost::tuple<unsigned int,std::string,base> tup2; tup2=tup1; tup2.get<2>().test(); std::cout << "Interesting value: " << tup2.get<0>() << '\n'; const boost::tuple<double,std::string,base> tup3(tup2); // Description Resource Path Location Type // assignment of read-only location tuple.cpp boost_tuple/src 45 C/C++ Problem // tup3.get<0>()=3.14; cut_off_rule(); boost::tuple<X,X,X> obj = boost::tuple<X,X,X>(string("Jaba"), string("Daba"), string("Duu")); // ok cut_off_rule(); double dNum = 5; boost::tuple<double&> numTuple(dNum); // ok // boost::tuple<double&>(dNum+3.14); // error: cannot initialize // non-const reference with a temporary boost::tuple<const double&>(dNum+3.14); // ok, but dangerous: // the element becomes a dangling reference cut_off_rule(); // char arr[2] = {'a', 'b'}; // boost::tuple<char[2]>(arr); // error, arrays can not be copied // boost::tuple<char[2], Y>(arr, Y()); // error, neither arrays nor Y can be copied boost::tuple<char[2], Y>(); // ok cut_off_rule(); boost::tuple<void (*)(int)> pFTuple1 = boost::make_tuple(&f); pFTuple1.get<0>()(10); boost::tuple<void (*)(int)> pFTuple2 = boost::make_tuple(boost::ref(f)); pFTuple2.get<0>()(20); boost::tuple<void (&)(int)> pFTuple3(f); pFTuple3.get<0>()(30); boost::tuple<boost::tuple<void (&)(int)> > pFTuple4(f); pFTuple4.get<0>().get<0>()(40); cut_off_rule(); // boost::tuple<int, char> stdPairToTuple = std::make_pair(1, 'a'); cut_off_rule(); boost::tuple<std::string, int, A> t1(std::string("same?"), 2, A()); boost::tuple<std::string, long> t2(std::string("same?"), 2); boost::tuple<std::string, long> t3(std::string("different"), 3); // t1 == t2; // true cut_off_rule(); int i; char c; boost::tie(i, c) = std::make_pair(1, 'a'); cout << i << " " << c << endl; cut_off_rule(); boost::tie(boost::tuples::ignore, c) = std::make_pair(1, 'a'); cout << c << endl; cut_off_rule(); int myX = -1; double myY = -2; boost::tuple<int, double> f2(2); boost::tie(myX, myY) = f2; // #2 cout << "myX = " << myX << ", myY = " <<myY << endl; } void cut_off_rule(void) { cout << "-----------------------------------" << endl; } void f(int i) { cout << "f(" << i << ")" << endl; }
tuple鏄痓oost搴撲腑涓涓被浼兼爣鍑唖td::pair搴撳簱錛屼絾pair鍙兘鏀寔涓ょ鍏冪礌錛岃宼uple鍒欏彲浠ユ敮鎸佸ぇ浜庝袱縐嶇殑銆?/p>
鏇村璇﹁В錛?a title="http://www.boost.org/doc/libs/1_42_0/libs/tuple/doc/tuple_users_guide.html" >http://www.boost.org/doc/libs/1_42_0/libs/tuple/doc/tuple_users_guide.html
浠ヤ笅鍐呭鐩存帴寮曡嚜鍘熸枃錛?/p>
鈥?..one of the most highly regarded and expertly designed C++ library projects in the world.鈥?鈥?Herb Sutter and Andrei Alexandrescu, C++ Coding Standards
A tuple (or n-tuple) is a fixed size collection of elements. Pairs, triples, quadruples etc. are tuples. In a programming language, a tuple is a data object containing other objects as elements. These element objects may be of different types.
Tuples are convenient in many circumstances. For instance, tuples make it easy to define functions that return more than one value.
Some programming languages, such as ML, Python and Haskell, have built-in tuple constructs. Unfortunately C++ does not. To compensate for this "deficiency", the Boost Tuple Library implements a tuple construct using templates.
Advanced features (describes some metafunctions etc.).
Rationale behind some design/implementation decisions.
To use the library, just include:
#include "boost/tuple/tuple.hpp"
Comparison operators can be included with:
#include "boost/tuple/tuple_comparison.hpp"
To use tuple input and output operators,
#include "boost/tuple/tuple_io.hpp"
Both tuple_io.hpp
and tuple_comparison.hpp
include tuple.hpp
.
All definitions are in namespace ::boost::tuples
, but the most common names are lifted to namespace ::boost
with using declarations. These names are: tuple
, make_tuple
, tie
and get
. Further, ref
and cref
are defined directly under the ::boost
namespace.
A tuple type is an instantiation of the tuple
template. The template parameters specify the types of the tuple elements. The current version supports tuples with 0-10 elements. If necessary, the upper limit can be increased up to, say, a few dozen elements. The data element can be any C++ type. Note that void
and plain function types are valid C++ types, but objects of such types cannot exist. Hence, if a tuple type contains such types as elements, the tuple type can exist, but not an object of that type. There are natural limitations for element types that cannot be copied, or that are not default constructible (see 'Constructing tuples' below).
For example, the following definitions are valid tuple instantiations (A
, B
and C
are some user defined classes):
tuple<int>
tuple<double&, const double&, const double, double*, const double*>
tuple<A, int(*)(char, int), B(A::*)(C&), C>
tuple<std::string, std::pair<A, B> >
tuple<A*, tuple<const A*, const B&, C>, bool, void*>
The tuple constructor takes the tuple elements as arguments. For an n-element tuple, the constructor can be invoked with k arguments, where 0 <= k <= n. For example:
tuple<int, double>()
tuple<int, double>(1)
tuple<int, double>(1, 3.14)
If no initial value for an element is provided, it is default initialized (and hence must be default initializable). For example.
class X {
X();
public:
X(std::string);
};
tuple<X,X,X>() // error: no default constructor for X
tuple<X,X,X>(string("Jaba"), string("Daba"), string("Duu")) // ok
In particular, reference types do not have a default initialization:
tuple<double&>() // error: reference must be
// initialized explicitly
double d = 5;
tuple<double&>(d) // ok
tuple<double&>(d+3.14) // error: cannot initialize
// non-const reference with a temporary
tuple<const double&>(d+3.14) // ok, but dangerous:
// the element becomes a dangling reference
Using an initial value for an element that cannot be copied, is a compile time error:
class Y {
Y(const Y&);
public:
Y();
};
char a[10];
tuple<char[10], Y>(a, Y()); // error, neither arrays nor Y can be copied
tuple<char[10], Y>(); // ok
Note particularly that the following is perfectly ok:
Y y;
tuple<char(&)[10], Y&>(a, y);
It is possible to come up with a tuple type that cannot be constructed. This occurs if an element that cannot be initialized has a lower index than an element that requires initialization. For example: tuple<char[10], int&>
.
In sum, the tuple construction is semantically just a group of individual elementary constructions.
make_tuple
functionTuples can also be constructed using the make_tuple
(cf. std::make_pair
) helper functions. This makes the construction more convenient, saving the programmer from explicitly specifying the element types:
tuple<int, int, double> add_multiply_divide(int a, int b) {
return make_tuple(a+b, a*b, double(a)/double(b));
}
By default, the element types are deduced to the plain non-reference types. E.g.:
void foo(const A& a, B& b) {
...
make_tuple(a, b);
The make_tuple
invocation results in a tuple of type tuple<A, B>
.
Sometimes the plain non-reference type is not desired, e.g. if the element type cannot be copied. Therefore, the programmer can control the type deduction and state that a reference to const or reference to non-const type should be used as the element type instead. This is accomplished with two helper template functions: ref
and cref
. Any argument can be wrapped with these functions to get the desired type. The mechanism does not compromise const correctness since a const object wrapped with ref
results in a tuple element with const reference type (see the fifth example below). For example:
A a; B b; const A ca = a;
make_tuple(cref(a), b); // creates tuple<const A&, B>
make_tuple(ref(a), b); // creates tuple<A&, B>
make_tuple(ref(a), cref(b)); // creates tuple<A&, const B&>
make_tuple(cref(ca)); // creates tuple<const A&>
make_tuple(ref(ca)); // creates tuple<const A&>
Array arguments to make_tuple
functions are deduced to reference to const types by default; there is no need to wrap them with cref
. For example:
make_tuple("Donald", "Daisy");
This creates an object of type tuple<const char (&)[7], const char (&)[6]>
(note that the type of a string literal is an array of const characters, not const char*
). However, to get make_tuple
to create a tuple with an element of a non-const array type one must use the ref
wrapper.
Function pointers are deduced to the plain non-reference type, that is, to plain function pointer. A tuple can also hold a reference to a function, but such a tuple cannot be constructed with make_tuple
(a const qualified function type would result, which is illegal):
void f(int i);
...
make_tuple(&f); // tuple<void (*)(int)>
...
volnet:
boost::tuple<void (&)(int)> pFTuple3(f);
pFTuple3.get<0>()(30);
tuple<tuple<void (&)(int)> > a(f) // ok
make_tuple(f); // not ok
Tuple elements are accessed with the expression:
t.get<N>()
or
get<N>(t)
where t
is a tuple object and N
is a constant integral expression specifying the index of the element to be accessed. Depending on whether t
is const or not, get
returns the N
th element as a reference to const or non-const type. The index of the first element is 0 and thus N
must be between 0 and k-1
, where k
is the number of elements in the tuple. Violations of these constraints are detected at compile time. Examples:
double d = 2.7; A a;
tuple<int, double&, const A&> t(1, d, a);
const tuple<int, double&, const A&> ct = t;
...
int i = get<0>(t); i = t.get<0>(); // ok
int j = get<0>(ct); // ok
get<0>(t) = 5; // ok
get<0>(ct) = 5; // error, can't assign to const
...
double e = get<1>(t); // ok
get<1>(t) = 3.14; // ok
get<2>(t) = A(); // error, can't assign to const
A aa = get<3>(t); // error: index out of bounds
...
++get<0>(t); // ok, can be used as any variable
Note! The member get functions are not supported with MS Visual C++ compiler. Further, the compiler has trouble with finding the non-member get functions without an explicit namespace qualifier. Hence, all get
calls should be qualified as: tuples::get<N>(a_tuple)
when writing code that should compile with MSVC++ 6.0.
A tuple can be copy constructed from another tuple, provided that the element types are element-wise copy constructible. Analogously, a tuple can be assigned to another tuple, provided that the element types are element-wise assignable. For example:
class A {};
class B : public A {};
struct C { C(); C(const B&); };
struct D { operator C() const; };
tuple<char, B*, B, D> t;
...
tuple<int, A*, C, C> a(t); // ok
a = t; // ok
In both cases, the conversions performed are: char -> int
, B* -> A*
(derived class pointer to base class pointer), B -> C
(a user defined conversion) and D -> C
(a user defined conversion).
Note that assignment is also defined from std::pair
types:
tuple<float, int> a = std::make_pair(1, 'a');
volnet:(Eclipse with MinGW g++
conversion from `std::pair<int, char>' to non-scalar type `boost::tuples::tuple<float, int, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type, boost::tuples::null_type>' requested
Tuples reduce the operators ==, !=, <, >, <=
and >=
to the corresponding elementary operators. This means, that if any of these operators is defined between all elements of two tuples, then the same operator is defined between the tuples as well. The equality operators for two tuples a
and b
are defined as:
a == b
iff for each i
: ai == bi
a != b
iff exists i
: ai != bi
The operators <, >, <=
and >=
implement a lexicographical ordering.
Note that an attempt to compare two tuples of different lengths results in a compile time error. Also, the comparison operators are "short-circuited": elementary comparisons start from the first elements and are performed only until the result is clear.
Examples:
tuple<std::string, int, A> t1(std::string("same?"), 2, A());
tuple<std::string, long, A> t2(std::string("same?"), 2, A());
tuple<std::string, long, A> t3(std::string("different"), 3, A());
bool operator==(A, A) { std::cout << "All the same to me..."; return true; }
t1 == t2; // true
t1 == t3; // false, does not print "All the..."
Tiers are tuples, where all elements are of non-const reference types. They are constructed with a call to the tie
function template (cf. make_tuple
):
int i; char c; double d;
...
tie(i, c, a);
The above tie
function creates a tuple of type tuple<int&, char&, double&>
. The same result could be achieved with the call make_tuple(ref(i), ref(c), ref(a))
.
A tuple that contains non-const references as elements can be used to 'unpack' another tuple into variables. E.g.:
int i; char c; double d;
tie(i, c, d) = make_tuple(1,'a', 5.5);
std::cout << i << " " << c << " " << d;
This code prints 1 a 5.5
to the standard output stream. A tuple unpacking operation like this is found for example in ML and Python. It is convenient when calling functions which return tuples.
The tying mechanism works with std::pair
templates as well:
int i; char c;
tie(i, c) = std::make_pair(1, 'a');
There is also an object called ignore
which allows you to ignore an element assigned by a tuple. The idea is that a function may return a tuple, only part of which you are interested in. For example (note, that ignore
is under the tuples
subnamespace):
char c;
tie(tuples::ignore, c) = std::make_pair(1, 'a');
The global operator<<
has been overloaded for std::ostream
such that tuples are output by recursively calling operator<<
for each element.
Analogously, the global operator>>
has been overloaded to extract tuples from std::istream
by recursively calling operator>>
for each element.
The default delimiter between the elements is space, and the tuple is enclosed in parenthesis. For Example:
tuple<float, int, std::string> a(1.0f, 2, std::string("Howdy folks!");
cout << a;
outputs the tuple as: (1.0 2 Howdy folks!)
The library defines three manipulators for changing the default behavior:
set_open(char)
defines the character that is output before the first element.
set_close(char)
defines the character that is output after the last element.
set_delimiter(char)
defines the delimiter character between elements.Note, that these manipulators are defined in the tuples
subnamespace. For example:
cout << tuples::set_open('[') << tuples::set_close(']') << tuples::set_delimiter(',') << a;
outputs the same tuple a
as: [1.0,2,Howdy folks!]
The same manipulators work with operator>>
and istream
as well. Suppose the cin
stream contains the following data:
(1 2 3) [4:5]
The code:
tuple<int, int, int> i;
tuple<int, int> j;
cin >> i;
cin >> tuples::set_open('[') >> tuples::set_close(']') >> tuples::set_delimiter(':');
cin >> j;
reads the data into the tuples i
and j
.
Note that extracting tuples with std::string
or C-style string elements does not generally work, since the streamed tuple representation may not be unambiguously parseable.
All tuple access and construction functions are small inlined one-liners. Therefore, a decent compiler can eliminate any extra cost of using tuples compared to using hand-written tuple like classes. Particularly, with a decent compiler there is no performance difference between this code:
class hand_made_tuple {
A a; B b; C c;
public:
hand_made_tuple(const A& aa, const B& bb, const C& cc)
: a(aa), b(bb), c(cc) {};
A& getA() { return a; };
B& getB() { return b; };
C& getC() { return c; };
};
hand_made_tuple hmt(A(), B(), C());
hmt.getA(); hmt.getB(); hmt.getC();
and this code:
tuple<A, B, C> t(A(), B(), C());
t.get<0>(); t.get<1>(); t.get<2>();
Note, that there are widely used compilers (e.g. bcc 5.5.1) which fail to optimize this kind of tuple usage.
Depending on the optimizing ability of the compiler, the tier mechanism may have a small performance penalty compared to using non-const reference parameters as a mechanism for returning multiple values from a function. For example, suppose that the following functions f1
and f2
have equivalent functionalities:
void f1(int&, double&);
tuple<int, double> f2();
Then, the call #1 may be slightly faster than #2 in the code below:
int i; double d;
...
f1(i,d); // #1
tie(i,d) = f2(); // #2
volnet:
int myX = -1;
double myY = -2;
boost::tuple<int, double> f2(2);
boost::tie(myX, myY) = f2; // #2
cout << "myX = " << myX << ", myY = " <<myY << endl;
See [1, 2] for more in-depth discussions about efficiency.
Compiling tuples can be slow due to the excessive amount of template instantiations. Depending on the compiler and the tuple length, it may be more than 10 times slower to compile a tuple construct, compared to compiling an equivalent explicitly written class, such as the hand_made_tuple
class above. However, as a realistic program is likely to contain a lot of code in addition to tuple definitions, the difference is probably unnoticeable. Compile time increases between 5 and 10 percent were measured for programs which used tuples very frequently. With the same test programs, memory consumption of compiling increased between 22% to 27%. See [1, 2] for details.
The library code is(?) standard C++ and thus the library works with a standard conforming compiler. Below is a list of compilers and known problems with each compiler:
Compiler
Problems
gcc 2.95
-
edg 2.44
-
Borland 5.5
Can't use function pointers or member pointers as tuple elements
Metrowerks 6.2
Can't use ref
and cref
wrappers
MS Visual C++
No reference elements (tie
still works). Can't use ref
and cref
wrappers
Gary Powell has been an indispensable helping hand. In particular, stream manipulators for tuples were his idea. Doug Gregor came up with a working version for MSVC, David Abrahams found a way to get rid of most of the restrictions for compilers not supporting partial specialization. Thanks to Jeremy Siek, William Kempf and Jens Maurer for their help and suggestions. The comments by Vesa Karvonen, John Max Skaller, Ed Brey, Beman Dawes, David Abrahams and Hartmut Kaiser helped to improve the library. The idea for the tie mechanism came from an old usenet article by Ian McCulloch, where he proposed something similar for std::pairs.
[1] J盲rvi J.: Tuples and multiple return values in C++, TUCS Technical Report No 249, 1999.
[2] J盲rvi J.: ML-Style Tuple Assignment in Standard C++ - Extending the Multiple Return Value Formalism, TUCS Technical Report No 267, 1999.
[3] J盲rvi J.:Tuple Types and Multiple Return Values, C/C++ Users Journal, August 2001.
Last modified 2003-09-07
漏 Copyright Jaakko J盲rvi 2001. Permission to copy, use, modify, sell and distribute this software and its documentation is granted provided this copyright notice appears in all copies. This software and its documentation is provided "as is" without express or implied warranty, and with no claim as to its suitability for any purpose.
鍘熸枃閾炬帴錛?a href="http://www.shnenglu.com/mymsdn/archive/2009/03/06/quicksort.aspx">http://www.shnenglu.com/mymsdn/archive/2009/03/06/quicksort.aspx 錛堟湭淇錛?/p>
鍏充簬淇BUG鍚庣殑浠g爜錛屽皢鍦ㄦ湰鏂囦腑鎻愪緵錛屽師鏂囦腑涓嶈繘琛屼慨鏀癸紝浣嗕細鏈夋彁紺烘寚鏄庢槸閿欒鐨勶紝鏈夊叴瓚g殑鏈嬪弸涔熷彲浠ョ洿鎺ュ湪鍘熸枃鐨勪唬鐮佷腑瀵繪壘閿欒鏉ラ敾鐐艱嚜宸辨帓閿欑殑鑳藉姏銆?/p>
涓嬮潰灝辨槸鍑犳浠g爜錛?/p>
Algorithms.cpp
#include "StdAfx.h" #include "Algorithms.h" Algorithms::Algorithms(void) { } Algorithms::~Algorithms(void) { }
Algorithms.h
#pragma once #include <iostream> class Algorithms { public: Algorithms(void); ~Algorithms(void); public: template <typename T> static void QuickSort(T* arr, size_t min, size_t max); private: template <typename T> static size_t qsort_helper_partition(T* arr, size_t min, size_t max); template <typename T> static inline void swap(T* arr, size_t x, size_t y); // helper template <typename T> static inline void helper_show_all(T* arr, size_t min, size_t max, char *msg); }; template <typename T> void Algorithms::QuickSort(T* arr, size_t min, size_t max) { if(min >= max || max == 0 - 1) return; helper_show_all(arr, min, max, "before qsort_helper_partition"); size_t p = qsort_helper_partition(arr, min, max); helper_show_all(arr, min, max, "after qsort_helper_partition"); QuickSort(arr, min, p - 1); QuickSort(arr, p + 1, max); } /* * @BUG: bug200910280001 * @DESC: 鐢變簬鍦ㄥ驚鐜痺hile(true)涓紝鍋囪鍘熶唬鐮? 01 while(true) 02 { 03 while(cmp < arr[i]) 04 ++i; 05 while(arr[j] < cmp) 06 --j; 07 if(i >= j) break; 08 09 swap(arr, i, j); 10 } 涓紝鍓嶄袱孌碉紙琛屽彿錛岃鍙鳳級涓殑浠g爜鍧囪繑鍥瀎alse錛? 鍒欐棤娉曡繘鍏?+i鎴栬?-j錛岄偅涔堝湪榪欎釜while(true)涓紝 i鍜宩鐨勫煎皢鏃犳硶鍙戠敓鍙樺寲錛屼粠鑰屽鑷存寰幆銆? @LINK:http://www.shnenglu.com/mymsdn/archive/2009/03/06/quicksort.aspx#99606 */ template <typename T> size_t Algorithms::qsort_helper_partition(T* arr, size_t min, size_t max) { T cmp = arr[min]; int i = min, j = max; // bug200910280001:淇i = min+1錛屽皢+1鐨勫姩浣滄斁鍦ㄥ驚鐜唴銆? while(true) { while(cmp < arr[++i]) // bug200910280001:灝嗗師鏈湪寰幆澶栫殑min+1錛岀Щ榪涘驚鐜唴錛屽茍棣栧厛+1 ; // bug200910280001:灝?+1縐昏嚦while鏉′歡涓? while(arr[j] < cmp) --j; if(i >= j) break; helper_show_all(arr, min, max, "before swap(arr, i, j)"); swap(arr, i, j); helper_show_all(arr, min, max, "after swap(arr, i, j)"); } swap(arr, min, j); return j; } template <typename T> void Algorithms::swap(T* arr, size_t x, size_t y) { T tmp = arr[x]; arr[x] = arr[y]; arr[y] = tmp; } template <typename T> void Algorithms::helper_show_all(T* arr, size_t min, size_t max, char *msg) { std::cout << "current array :\t"; for(int i = min; i < max; ++i) { std::cout << arr[i] << " "; } std::cout<<"\t//"<<msg; std::cout<<std::endl; }
cpp_quickSort.cpp
// cpp_quickSort.cpp : 瀹氫箟鎺у埗鍙板簲鐢ㄧ▼搴忕殑鍏ュ彛鐐廣? // #include "stdafx.h" #include "Algorithms.h" #include <iostream> #include <vector> #include <algorithm> int _tmain(int argc, _TCHAR* argv[]) { int arr_begin = 0; int arr_length = 12; //The length will instead of the magic numbers int arr[] = {8, 3, 7, 1, 5, 6, 2, 1, 9, 9, 1, 1}; // Test for : 20091028bug0001 // int arr[] = {1, 1, 1}; std::cout << "input array :\t"; for(size_t i = arr_begin; i != arr_length; ++i) { std::cout<<arr[i]<<" "; } std::cout<<std::endl; Algorithms::QuickSort(arr, arr_begin, arr_length); std::cout << "result array :\t"; for(size_t i = arr_begin; i != arr_length; ++i) { std::cout<<arr[i]<<" "; } std::cout<<std::endl; std::cout << "--------------------" << std::endl; std::cout << "input array :\t"; std::vector<int> vec; vec.push_back(3); vec.push_back(1); vec.push_back(4); vec.push_back(1); vec.push_back(7); vec.push_back(6); for(std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++ iter) { std::cout<<*iter<<" "; } std::cout<<std::endl; std::sort(vec.begin(), vec.end()); for(std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++ iter) { std::cout<<*iter<<" "; } std::cout<<std::endl; return 0; }
鍙﹀錛岄檮C FAQ涓婂叧浜巒ull pointer鐨勮В閲婏細C FAQ錛歯ull pointer
鍘熺悊錛屽洜涓?鐨?0嬈℃柟灝辨槸1MB錛?鐨?0嬈℃柟涓?KB錛?鐨?0嬈℃柟涓?GB錛屼互姝ょ被鎺級銆?/p>
濡傛灉浣犺姹傚垎閰嶇殑鍐呭瓨鍧楀皬浜?MB錛屼綘寰楀埌鐨勫唴瀛樻槸鍚︽瘮榪欒澶氫竴浜涘憿錛熶負浠涔堬紵
絳旓細
榪欎笉鏄粷瀵圭殑錛?/p>
鍦ㄦ湰渚嬩腑浣跨敤
1<<22錛?MB錛夊緱鍒扮殑緇撴灉涔?鏄?000MB
1<<21錛?MB錛夊緱鍒扮殑緇撴灉涔?鏄?972MB
1<<20錛?MB錛夊緱鍒扮殑緇撴灉鏄?918MB
1<<19錛?.5MB錛夊緱鍒扮殑緇撴灉闄?鏄?812MB
1<<18錛?.25MB錛夊緱鍒扮殑緇撴灉闄?鏄?003MB
1<<17錛?.125MB錛夊緱鍒扮殑緇撴灉闄?鏄?034MB
鏄劇劧鍑虹幇浜嗕竴涓剰澶栫殑緇撴灉銆?/p>
#include <stdio.h> #include <stdlib.h> char * favorite_fruit1(void); char * favorite_fruit2(void); void favorite_fruit3(char **); int main(void) { char * fruit1 = favorite_fruit1(); printf("%s\n", fruit1); char * fruit2 = favorite_fruit2(); printf("%s\n", fruit2); char * fruit3 = NULL; favorite_fruit3(&fruit3); printf("%s\n", fruit3); printf("------END of CODE------"); return EXIT_SUCCESS; } char * favorite_fruit1(void){ char deciduous[] = "apple"; return deciduous; } char * favorite_fruit2(void){ static char deciduous[] = "apple"; return deciduous; } void favorite_fruit3(char ** fruit){ static char deciduous[] = "apple"; *fruit = deciduous; }
favorite_fruit1寰堟槑鏄句細鍑虹幇闂錛屽師鍥犳槸鍥犱負char deciduous[]鏄眬閮ㄥ彉閲忥紝鍦ㄥ嚱鏁拌皟鐢ㄨ繑鍥炲悗錛屽氨閲婃斁浜嗐?/p>
favorite_fruit2鍥犱負浣跨敤浜唖tatic錛岃宻tatic闄愬畾浜嗗彉閲忚淇濆瓨鍦ㄦ暟鎹錛坉ata segment錛変腑錛屽畠鐨勫0鏄庡懆鏈熷悓紼嬪簭涓鏍烽暱銆傛墍浠ヤ笉浼氬嚭閿欍?/p>
favorite_fruit3鏄彟涓縐嶆湁鏁堢殑鍐欐硶錛屽叾鍘熺悊鍚?銆?/p>
2銆佹棭鏈熺殑gets()涓殑Bug瀵艱嚧浜咺nternet锠曡櫕錛圥42錛?/p>
gets()鍑芥暟騫朵笉媯鏌ョ紦鍐插尯鐨勭┖闂達紝浜嬪疄涓婂畠涔熸棤娉曟鏌ョ紦鍐插尯鐨勭┖闂淬傚鏋滃嚱鏁扮殑璋冪敤鑰呮彁渚涗簡涓涓寚鍚戝爢鏍堢殑鎸囬拡錛屽茍涓攇ets()鍑芥暟璇誨叆鐨勫瓧絎︽暟閲忚秴榪囩紦鍐插尯鐨勭┖闂達紝gets()鍑芥暟灝嗕細鎰夊揩鍦板皢澶氬嚭鏉ョ殑瀛楃緇х畫鍐欏叆鍒板爢鏍堜腑錛岃繖灝辮鐩栦簡鍫嗘爤鍘熷厛鐨勫唴瀹廣傗斺旇繖灝辨槸鐥呮瘨鍒╃敤瀹冩潵鍐欏叆棰濆絀洪棿錛屽茍寮曞彂锠曡櫕鐥呮瘨鐨勫墠鎻愩?/p>
鎺ㄨ崘鐨勬柟寮忔槸灝?/p>
gets(line)
鏇挎崲涓?/p>
if(fgets(line, sizeof(line), stdin) == NULL)
exit(1);
3銆佺浉閭誨瓧絎︿覆甯擱噺鑷姩榪炴帴錛圥45錛?/p>
榪欎釜鍏跺疄宸茬粡搴旂敤寰堟櫘閬嶄簡錛屼絾鏄垜涓漢鐢ㄧ殑姣旇緝灝戯紝鐗規璁板綍涓涓嬨?/p>
4銆佽繑鍥炰竴涓寚閽堬紵錛圥48錛?/p>
榪欎釜璇濋鍥寸粫涓涓▼搴忕殑BUG鏉ュ睍寮錛岃繖涓▼搴忚繑鍥炰簡灞閮ㄥ彉閲忕殑鍊肩殑鎸囬拡錛岃繖涔堣褰撶劧浣犱竴鐪煎氨鑳界湅寰楀嚭鏉ラ棶棰樻墍鍦紝浣嗘槸鍦ㄥ緢澶氭椂鍊欙紝榪欎釜閿欒鍗存繪槸鍦ㄤ綘鐨勭溂鐨瓙搴曚笅婧滆蛋銆?/p>
浣滆呮彁渚涗簡浜旂鏂瑰紡錛屽彧鑳借鍙互鐢紝浣嗗敮涓鎺ㄨ崘鐨勫彧鏈変竴涓紝璇﹁浣滆呯殑鍒嗘瀽錛圥48錛夛紙涓嶆槸浠涔堥珮娣辯殑鐞嗚錛屼綘鑷繁涔熻兘鍒嗘瀽鍦板嚭鏉ワ級銆?/p>
a.榪斿洖涓涓瓧絎︿覆甯擱噺鐨勬寚閽堛傚洜涓哄父閲忓瓨鍦ㄩ潤鎬佹暟鎹瓨鍌ㄥ尯錛屾墍浠ユ寚閽堟病闂銆?/p>
b.浣跨敤鍏ㄥ眬澹版槑鐨勬暟緇勩傛彁鍒板叏灞涓や釜瀛楋紝灝辯煡閬撹繖涓柟娉曟湁寰堝ぇ鐨勫眬闄愭с?/p>
c.浣跨敤闈欐佹暟緇勩備笅涓嬈¤皟鐢ㄥ皢瑕嗙洊榪欎釜鏁扮粍鍐呭銆?/p>
char * func() {
static char buffer[20];
鈥?/p>
return buffer;
}
d.鏄懼紡鍒嗛厤涓浜涘唴瀛橈紝淇濆瓨榪斿洖鐨勫箋?/p>
char * func() {
char * s = malloc(120);
鈥?/p>
return s;
}
鏃㈢劧鐢ㄥ埌浜唌alloc錛屽氨蹇呯劧浼撮殢鐫free錛屽洜姝ゅ甫鏉ヤ簡鍐呭瓨綆$悊鐨勯棶棰橈紝澧炲姞浜嗗紑鍙戣呰礋鎷呫?/p>
e.錛?u>鎺ㄨ崘錛夊湪璋冪敤鍓嶅悗錛岀敱鍑芥暟璋冪敤鑰呭垎閰嶅唴瀛橈紝騫剁敱鍏墮噴鏀撅紝鍦ㄥ悓涓鍦版柟閲婃斁瀵逛簬鍐呭瓨綆$悊鏉ヨ浠d環鐩稿鏈灝忋?/p>
void func( char * result, int size) {
鈥?/p>
strncpy(result, 鈥淭hat鈥檇 be in the data segment, Bob鈥? size);
}
buffer = malloc(size);
func(buffer, size);
鈥?/p>
free(buffer);
鏈枃浠g爜宸茬粡鏇存柊錛屼慨姝d弗閲岯UG錛屾渶鏂扮増鏈瑙併?a href="http://www.shnenglu.com/mymsdn/archive/2009/10/28/quicksort20091028.html">QuickSort蹇熸帓搴忔硶(2009-10-28)銆嬶紒
鏈枃涓墍娑夊強鐨勪唬鐮佹湭鍋氭洿鏂幫紝璇風Щ姝ユ渶鏂扮増鏌ラ槄姝g‘浠g爜錛?/p>
閾炬帴錛?a title="http://www.shnenglu.com/mymsdn/archive/2009/10/28/quicksort20091028.html" href="http://www.shnenglu.com/mymsdn/archive/2009/10/28/quicksort20091028.html">http://www.shnenglu.com/mymsdn/archive/2009/10/28/quicksort20091028.html
蹇熸帓搴忔硶錛氾紙濂藉湡錛屾劅瑙夋弧涓栫晫閮戒細錛屼笉榪囪繕鏄啓涓涓嬶紝褰撶劧浜嗭紝鏍囧噯搴撻噷澶氱殑鏄帓搴忕畻娉曪級錛岃繖閲岃繕鏄疄鐜扮粡鍏哥増鐨勫揩閫熸帓搴忎簡錛屾椂闂村鏉傚害O(nlogn)
Algorithms.h
#pragma once #include <iostream> class Algorithms { public: Algorithms(void); ~Algorithms(void); public: template <typename T> static void QuickSort(T* arr, size_t min, size_t max); private: template <typename T> static size_t qsort_helper_partition(T* arr, size_t min, size_t max); template <typename T> static inline void swap(T* arr, size_t x, size_t y); }; template <typename T> void Algorithms::QuickSort(T* arr, size_t min, size_t max) { if(min >= max || max == 0 - 1) return; size_t p = qsort_helper_partition(arr, min, max); QuickSort(arr, min, p - 1); QuickSort(arr, p + 1, max); } template <typename T> size_t Algorithms::qsort_helper_partition(T* arr, size_t min, size_t max) { T cmp = arr[min]; int i = min + 1, j = max; while(true) { while(cmp < arr[i]) ++i; while(arr[j] < cmp) --j; if(i >= j) break; swap(arr, i, j); } swap(arr, min, j); return j; } template <typename T> void Algorithms::swap(T* arr, size_t x, size_t y) { T tmp = arr[x]; arr[x] = arr[y]; arr[y] = tmp; }
鐢ㄦ硶錛氾紙欏轟究鏈夋爣鍑嗗簱鐨勬帓搴忔硶錛屽綋鐒跺彧鏄皟涓涓嬶紝娌℃湁浠涔堝彲璇寸殑浜嗭級
#include "Algorithms.h" #include <iostream> #include <vector> #include <algorithm> int _tmain(int argc, _TCHAR* argv[]) { int arr[] = {4, 8, 3, 7, 1, 5, 6, 2}; for(size_t i = 0; i != 8; ++i) { std::cout<<arr[i]<<" "; } std::cout<<std::endl; Algorithms::QuickSort(arr,0, 7); for(size_t i = 0; i != 8; ++i) { std::cout<<arr[i]<<" "; } std::cout<<std::endl; std::vector<int> vec; vec.push_back(3); vec.push_back(1); vec.push_back(4); vec.push_back(1); vec.push_back(7); vec.push_back(6); for(std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++ iter) { std::cout<<*iter<<" "; } std::cout<<std::endl; std::sort(vec.begin(), vec.end()); for(std::vector<int>::iterator iter = vec.begin(); iter != vec.end(); ++ iter) { std::cout<<*iter<<" "; } std::cout<<std::endl; return 0; }