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

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

INVALID_HANDLE_VALUE 、 NULL、nullptr 和 nullptr_t 的联系

發布時間:2024/10/14 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 INVALID_HANDLE_VALUE 、 NULL、nullptr 和 nullptr_t 的联系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
--------------------------------------------- -- 時間:2018-12-26 -- 創建人:Ruo_Xiao -- 郵箱:xclsoftware@163.com ---------------------------------------------

一、INVALID_HANDLE_VALUE?

1、源碼

// WinNT.h typedef void *HANDLE; // BaseTsd.h typedef _W64 long LONG_PTR, *PLONG_PTR; // WinBase.h #define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)

2、解析

(1)HANDLE?實際上是?void?指針類型,-1 經過(HANDLE)(LONG_PTR)之后,轉成了?0xffffffff?

(2)原因:

-1 的二進制為 1000 0000 0000 0000 0000 0000 0000 0001,但數據在內存中是以補碼形式存在的,故內存中存儲的數據為 1111 1111 1111 1111 1111 1111 1111 1111,按照?void*?去讀取時,該值的結果為:0xffff ffff 了。

二、NULL

我們知道,在 C 語言中,NULL 通常被定義為:#define NULL ((void *)0)

所以說 NULL 實際上是一個空指針,如果在 C 語言中寫入以下代碼,編譯是沒有問題的,因為在C語言中把空指針賦給 int 和 char 指針的時候,發生了隱式類型轉換,把 void 指針轉換成了相應類型的指針。

int *pi = NULL; char *pc = NULL;

但是問題來了,以上代碼如果使用 C++ 編譯器來編譯則是會出錯的,因為 C++ 是強類型語言,void* 是不能隱式轉換成其他類型的指針的,所以實際上編譯器提供的頭文件做了相應的處理:

#ifdef __cplusplus #define NULL 0 #else #define NULL ((void *)0) #endif

可見,在 C++ 中,NULL 實際上是 0。因為 C++ 中不能把 void* 類型的指針隱式轉換成其他類型的指針,所以為了解決空指針的表示問題,C++ 引入了 0 來表示空指針,這樣就有了上述代碼中的 NULL 宏定義。

但是實際上,用NULL代替 0 表示空指針在函數重載時會出現問題,程序執行的結果會與我們的想法不同,舉例如下:

#include <iostream> using namespace std;void func(void* i) {cout << "func1" << endl; }void func(int i) {cout << "func2" << endl; }void main(int argc,char* argv[]) {func(NULL);func(nullptr);getchar(); }

在這段代碼中,我們對函數 func 進行可重載,參數分別是 void* 類型和 int 類型,但是運行結果卻與我們使用 NULL 的初衷是相違背的,因為我們本來是想用 NULL 來代替空指針,但是在將 NULL 輸入到函數中時,它卻選擇了 int 形參這個函數版本,所以是有問題的,這就是用 NULL 代替空指針在 C++ 程序中的二義性。

為了解決上述問題,C++11 引入了 nullptr,專門表示空指針。

三、nullptr

從上面的例子中我們可以看到,使用 nullptr 作為實參,確實選擇了正確的以 void* 作為形參的函數版本。

此時又引入了新的問題,如下所示:

#include <cstddef> #include <iostream>void f(int* pi) {std::cout << "Pointer to integer overload\n"; }void f(double* pd) {std::cout << "Pointer to double overload\n"; }int main() {int* pi; double* pd;f(pi);f(pd);f(nullptr); // 不知調用哪個重載函數。 }

四、nullptr_t

std::nullptr_t?是空指針字面量?nullptr?的類型。它是既非指針類型亦非指向成員指針類型的獨立類型。

對于nullptr_t 的類型可以定義如下:?

class nullptr_t { public: template<class T> inline operator T*() const //定義類型轉換操作符,使nullptr_t 可轉為任意非類成員指針類型 { return 0; } //重載類型轉換操作符,使 nullptr_t 可以轉換為類 C 中任意的指針類型(數據成員指針/函數成員指針) //對類中數據成員的指針,T 將被推導為數據成員的類型 eg: int (X::*); 此時 T 為 int,C 為 X //對類中函數成員的指針,T 將被推導為函數成員的類型 eg: int (X::*)(int); 此時T 等效于: typedef int (T)(int) template<class C, class T> inline operator T C::*() const { return 0; } private: void operator&() const; }; const null_ptr nullptr = {}

引入 nullptr_t 目的就是為了解決多個重載函數中,形參均為指針時傳入 nullptr 不知調用哪一個的問題。

#include <cstddef> #include <iostream>void f(int* pi) {std::cout << "Pointer to integer overload\n"; }void f(double* pd) {std::cout << "Pointer to double overload\n"; }void f(std::nullptr_t nullp) {std::cout << "null pointer overload\n"; }int main() {int* pi; double* pd;f(pi);f(pd);f(nullptr); // 無 void f(nullptr_t) 可能有歧義// f(0); // 歧義調用:三個函數全部為候選// f(NULL); // 若 NULL 是整數空指針常量則為歧義// (如在大部分實現中的情況) }

?結果:

Pointer to integer overload Pointer to double overload null pointer overload

五、總結

句柄初始化,使用?INVALID_HANDLE_VALUE 。

指針初始化的方法有 NULL、nullptr。

NULL 在 C++ 中就是 0,這是因為在 C++ 中 void* 類型是不允許隱式轉換成其他類型的,所以之前 C++ 中用 0 來代表空指針,但是在重載整形的情況下,會出現上述的問題。所以,C++11 加入了 nullptr,可以保證在任何情況下都代表空指針,而不會出現上述的情況,因此,建議以后還是都用 nullptr 替代 NULL 吧,而 NULL 就當做 0 使用。

引入 nullptr_t 目的是解決重載函數的形參都為指針時,傳入 nullptr 歧義的問題。增加形參為 nullptr_t,可以明確告訴編譯器,對于形參為 nullptr 的調用,直接調用 nullptr_t 的版本。

?

(SAW:Game Over!)

?

總結

以上是生活随笔為你收集整理的INVALID_HANDLE_VALUE 、 NULL、nullptr 和 nullptr_t 的联系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。