NULL、nullptr、0剪不斷理還亂的關係

NULL 和 0 的歧義

先看下NULL的定義,在stddef.h中(/usr/lib/gcc/x86_64-redhat-linux/4.8.2/include/stddef.h)
在這裏插入圖片描述
在C中,NULL定義爲((void*)0)。
在C代碼中,一般用NULL表示空指針,即指針的0值。例如:

int *p = NULL;		// 正確
int *p = 0;		// 正確

在C++中,NULL定義爲0或者0L。(是0還是0L跟編譯器定義的頭文件有關)
在C++98代碼中,我們也只能用NULL來表示空指針。例如:

#include <iostream>
using namespace std;

class Test
{
public:
	void func()
	{}
};

int main()
{
	int *p = NULL;				// NULL表示普通指針的0值,即空指針
	int *p1 = 0;				// 同上
	void (Test::*p_func)() = NULL;		// NULL表示指向成員函數的指針的0值,函數指針
	void (Test::*p1_func)() = 0;		// 同上
}

// compile cmd
// g++ -g -std=c++11 main.cpp -o main

到現在爲止,似乎一切看起來都還挺好的,沒什麼歧義啊。那我們現在考慮C++函數重載的一種情況,如下:

#include <iostream>
using namespace std;

class Test
{
public:
	void func(int a)
	{
		cout << "call int.." << endl;
	}

	void func(bool b)
	{
		cout << "call bool.." << endl;
	}

	void func(void* c)
	{
		cout << "call void*.." << endl;
	}
};

int main()
{
	Test a;
	a.func(0);	// 調用func(int)
	a.func(NULL);	// 混亂,且編譯不通過
}

// compile cmd
// g++ -g -std=c++11 main.cpp -o main

按照我們編碼的意思,a.func(NULL)應該會調用func(void*)纔對,但是實際情況卻是編譯不通過,如下:
在這裏插入圖片描述
爲什麼呢?
1、a.func(0)這個沒問題,是因爲0被編譯器正確地、嚴格地認爲是int型,所以嚴格調用了func(int)。
2、但是NULL被認爲是0L,這時候沒有一個函數能嚴格匹配,所以0L就要被轉換,但是轉換成int、bool、void*都可以哪,所以編譯器就混亂了,不知道你到底想要調用哪個函數。
解決方案有三種:
case1:再定義一個func(long)函數,就可以使得NULL嚴格地和long匹配。

void func(long d)
{
	cout << "call long.." << endl;
}

但是,這時候編譯還是有warning,如下:
在這裏插入圖片描述
case2:就是不要讓廣義整型數和指針重載(這是C++98一個好的編程習慣)。
case3:引入nullptr。

引入nullptr

參考文章和鏈接

  1. https://www.cnblogs.com/DswCnblog/p/5629073.html
  2. https://www.cnblogs.com/xinxue/p/5415139.html
  3. https://blog.csdn.net/u011304970/article/details/72229013
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章