C++編程進階

來源:互聯網
上載者:User

標籤:

程式碼片段1:

//stdafx.h// stdafx.h : 標準系統包含檔案的包含檔案,// 或是經常使用但不常更改的// 特定於項目的包含檔案//#pragma once// 如果必須將位於下面指定平台之前的平台作為目標,請修改下列定義。// 有關不同平台對應值的最新資訊,請參考 MSDN。#ifndef WINVER     // 允許使用特定於 Windows XP 或更高版本的功能。#define WINVER 0x0501   // 將此值更改為相應的值,以適用於 Windows 的其他版本。#endif#ifndef _WIN32_WINNT   // 允許使用特定於 Windows XP 或更高版本的功能。#define _WIN32_WINNT 0x0501 // 將此值更改為相應的值,以適用於 Windows 的其他版本。#endif#ifndef _WIN32_WINDOWS   // 允許使用特定於 Windows 98 或更高版本的功能。#define _WIN32_WINDOWS 0x0410 // 將此值更改為適當的值,以指定將 Windows Me 或更高版本作為目標。#endif#ifndef _WIN32_IE    // 允許使用特定於 IE 6.0 或更高版本的功能。#define _WIN32_IE 0x0600 // 將此值更改為相應的值,以適用於 IE 的其他版本。#endif#define WIN32_LEAN_AND_MEAN   // 從 Windows 頭中排除極少使用的資料#include <stdio.h>#include <tchar.h>#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // 某些 CString 建構函式將是顯式的#ifndef VC_EXTRALEAN#define VC_EXTRALEAN   // 從 Windows 頭中排除極少使用的資料#endif#include <afx.h>#include <afxwin.h>         // MFC 核心組件和標準組件#include <afxext.h>         // MFC 擴充#ifndef _AFX_NO_OLE_SUPPORT#include <afxdtctl.h>   // MFC 對 Internet Explorer 4 公用控制項的支援#endif#ifndef _AFX_NO_AFXCMN_SUPPORT#include <afxcmn.h>    // MFC 對 Windows 公用控制項的支援#endif // _AFX_NO_AFXCMN_SUPPORT#include <iostream>// TODO: 在此處引用程式需要的其他標頭檔//stdafx.cpp// stdafx.cpp : 只包括標準包含檔案的源檔案// LANFILEMAN.pch 將作為先行編譯頭// stdafx.obj 將包含先行編譯類型資訊#include "stdafx.h"// TODO: 在 STDAFX.H 中// 引用任何所需的附加標頭檔,而不是在此檔案中引用//Defineh.h#include <WinSock2.h>#define SENDFILESIZE (10 * 1024 * 1024)#define SERVERMODE 1#define CLIENTMODE 2#define EXITAPP 2#define REDO 1#define MAXCLIENTNUM 10typedef enum RESULT{    FUNCSUCESS,           //函數執行成功    FUNCFAILD,             //一般的函數執行失敗    WSASTARTUP,    CREATESOCKET,    BINDSOCKET,    LISTEN,    ACCEPT,    CREATEFILE,    READFILE,    SEND,    RECV,    CONNECT,    WRITEFILE,    SETENDOFFILE,    CLOSESOCKET} Result;#define WSARETURN(NODE)                           if(nResult != 0)                             {        cout << "錯誤碼:" << WSAGetLastError() << GetString(NODE);        return NODE;    }#define WSACONTINUE(NODE)

程式碼片段2:關於MFC中的#ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #endif

情況1:
#ifdef _DEBUG
virtual void AssertValid() const;                 //assert(斷言)valid(有效,正確的)
virtual void Dump(CDumpContext& dc) const;        //儲存上下文
#endif

    這兩個函數是調試用的,第一個函數檢查可用性,即是否有效。第二個函數如果未更改的話,最終調用的是Cwnd::Dump();輸出視窗類名,標題名等一系列資訊(在輸出視窗中)。

#ifdef _DEBUG
#endif
這是條件編譯,即如果有#define _DEBUG這兩個函數會編譯,否則忽略。當你用debug產生時(相對於release)開發環境則自動的加上這個宏定義,這兩個函數有效。

情況2:
#ifdef _DEBUG                                   // 判斷是否定義_DEBUG
#undef THIS_FILE                                // 取消THIS_FILE的定義
static char THIS_FILE[]=__FILE__;               // 定義THIS_FILE指向檔案名稱
#define new DEBUG_NEW                           // 定義調試new宏,取代new關鍵字
#endif // 結束

    如果定義了_DEBUG,表示在調試狀態下編譯,因此相應修改了兩個符號的定義。
    THIS_FILE是一個char數組全域變數,字串值為當前檔案的全路徑,這樣在Debug版本中當程式出錯時出錯處理代碼可用這個變數告訴你是哪個檔案中的代碼有問題。
    定義 _DEBUG後,由於定義了_DEBUG,編譯器確定這是一個調試,編譯#ifdef _DEBUG和#endif之間的代碼。#undef 表示清除當前定義的宏,使得THIS_FILE無定義。
   __FILE__ 是編譯器能識別的事先定義的ANSI C 的6個宏之一。
   DEBUG_NEW定位記憶體泄露並且追蹤檔案名和行號。

情況3:
#ifdef _DEBUG                     //如果是debug狀態
#undef THIS_FILE                  //清除THIS_FILE
static char THIS_FILE[]=__FILE__; //定義THIS_FILE為__FILE__(這是當前檔案全路徑名字)
#define new DEBUG_NEW //定義new為DEBUG_NEW(這個可以檢測到記憶體泄露之類的問題,其實就是可以使用crt開頭的那幾個調試函數)
#endif

ANSI C 的6個宏:
__FILE__為先行編譯器常量,返回當前編譯的檔案名稱,還有比較常用的幾個先行編譯器常量;
__LINE__編譯器正在編譯的檔案的第幾行;
__DATE__返回當前的日期Jul-20-2004;
__TIME__返回當前的時間hh:mm:ss; 
__TIMESTAMP__ 的預定義的編譯器宏始終返回時間戳記資訊。在太平洋標準的時間內無論本地時間和CL.EXE 的運行位置在電腦上的時區。
__STDC__條件編譯,意思是:如果定義了標準C或c++,那麼編譯這句話後面直到#endif以前的原始碼。
_STDC__cplusplus這兩個都是標準宏,_STDC_表示是是否符合標準C;_cplusplus表示是否是C++。


      曾經一個解釋說,多次使用__FILE__宏,雖然得到字串的內容相同,但是可能地址不同,即同一個字串常量多次用到時佔用不同的地址,這樣導致需要的記憶體增加了。為了檢測內在泄露, Debug 版本的 new 附加上了調用 new 的檔案名稱與調用所在的行號資訊, 這是通過 __FILE__ 和 __LINE__ 來實現的, 這兩個屬於預定義的內部宏, 而之所以要用 THIS_FILE 來代替 __FILE__, 是為了減少程式大小: 如果你在一個檔案中有 10000 次對 new 的調用, 那麼會產生 10000 個當前檔案名稱的常量字串(第一個都是由 __FILE__ 宏擴充而來的), 最後產生的目標檔案會很大, 而用 THIS_FILE 來代替, 當前檔案名稱只有一份, 傳遞檔案名稱使用 THIS_FILE 指標就可以了。

    __FILE__和__LINE__一樣都是編譯器定義的宏。當碰到__FILE__時,編譯器會把__FILE__替換成一個字串,這個字串就是當前在編譯的檔案的路徑名。在DEBUG_NEW的定義中沒有直接使用__FILE__,而是用了THIS_FILE,其目的是為了減小目標檔案的大小。假設在某個cpp檔案中有100處使用了new,如果直接使用__FILE__,那編譯器會產生100個常量字串,這100個字串都是這個cpp檔案的路徑名,顯然十分冗餘。如果使用THIS_FILE,編譯器只會產生一個常量字串,那100處new的調用使用的都是指向常量字串的指標。
   
    在MFC中,可以使用 DEBUG_NEW 宏代替 new 運算子來協助定位記憶體流失。在程式的“Debug”版本中,DEBUG_NEW 將為所分配的每個對象追蹤檔案名和行號。當編譯器的“Release”版本時,DEBUG_NEW 將解析為不包含檔案名稱和行號資訊的簡單 new 操作。因此,在程式的“Release”版本中不會造成任何速度損失。  
   
    如果不想重寫整個程式來使用 DEBUG_NEW 代替 new,則可以在源檔案中定義下面的宏:  
   
    #define  new  DEBUG_NEW  
    當進行對象轉儲時,用 DEBUG_NEW 分配的每個對象均將顯示被分配到的檔案和行號,使您可以查明記憶體流失源。  
   
    MFC 架構的“Debug”版本自動使用 DEBUG_NEW,但代碼不自動使用它。如果希望利用 DEBUG_NEW 的好處,則必須顯式使用 DEBUG_NEW 或 #define new,如上所示。  

    總起來講,這段代碼的作用就是防止記憶體泄露,減小程式編譯開銷的。

 

C++編程進階

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.