事情緣起是因爲上班途中刷到了有個微博,那人說答對這個問題的請發簡歷。
看了就是關於指向C++類的指針的知識,原代碼類似下面這樣:
class NullPointCall
{
public:
void display()
{
std::cout << "It's nice!" << std::endl;
};
private:
int m_nNum;
};
問題類似於:
NullPointCall *pNull = NULL;
pNull->display();
// 求問結果是什麼
// A、coredump
// B、顯示It is nice!
// C、...(我忘了啥答案了 囧...)
// D、其他錯誤
然後參考了網上的博客,這有關this指針。
class NullPointCall
{
public:
static void Test1()
{
std::cout << m_nStaticInt << std::endl;
};
void Test2()
{
std::cout << "It is nice!" << std::endl;
};
void Test3(int nInputNum)
{
std::cout << nInputNum << std::endl;
};
void Test4()
{
std::cout << m_nVariable << std::endl;
};
private:
static int m_nStaticInt;
int m_nVariable;
};
int NullPointCall::m_staticInt = -10;
然後測試如下:
NullPointCall *pNull = NULL;
pNull->Test1();
pNull->Test2();
pNull->Test3(2);
pNull->Test4();
然後輸出爲:
-10
It is nice!
2
Test4()失敗,內存訪問衝突
對於類成員函數而言,並不是一個對象對應一個單獨的成員函數體,而是此類的所有對象共用這個成員函數體。 當程序被編譯之後,此成員函數地址即已確定。而成員函數之所以能把屬於此類的各個對象的數據區別開, 就是靠這個this指針。函數體內所有對類數據成員的訪問, 都會被轉化爲this->數據成員的方式。
當在類的非靜態成員函數中訪問類的非靜態成員的時候,編譯器會自動將對象本身的地址作爲一個隱含參數傳遞給函數。即使你沒有寫上this指針,編譯器在編譯的時候也是加上this的。
對於上面的例子來說,this的值也就是pNull的值。也就是說this的值爲NULL。
Test1()是靜態函數,編譯器不會給它傳遞this指針,所以call 1那行代碼可以正確調用(這裏相當於NullPointCall::Test1())。
對於Test2()和Test3()兩個成員函數,雖然編譯器會給這兩個函數傳遞this指針,但是它們並沒有通過this指針來訪問類的成員變量,所以Test2()和Test3()兩行代碼可以正確調用。
而對於成員函數Test4()要訪問類的成員變量,因此要使用this指針:
void NullPointCall::Test4(NullPointCall *this)
{
std::cout << this->m_nVariable << std::endl;
}
相當於:
void NullPointCall::Test4(NULL)
{
std::cout << this->m_nVariable << std::endl;
}
這個時候發現this指針的值爲NULL,就會造成程序的崩潰。