[英]C++ strange behaviour
請檢查此代碼。
class ex
{
int i;
public:
ex(int ii = 0):i(ii){}
~ex(){cout<<"dest"<<endl;}
void show()
{
cout<<"show fun called"<<endl;
}
};
int main(int argc , char *argv[])
{
ex *ob = NULL;
ob->show();
return 0;
}
當我們調用show方法時會發生什么。
謝謝..
ex *ob = NULL;
ob->show();
您正在取消引用會導致未定義行為的空指針。 這不好。
如果不清楚取消引用的位置,則可以理解->
運算符會轉換為(*ob).show()
。
這是未定義的行為。
話雖這么說,在大多數編譯器上,只要有空指針,您就可以調用方法
1)他們不訪問成員。
2)它們不是虛擬的。
大多數編譯器會翻譯
ob->show()
進入
call ob::show
這是應用程序空間中存在的有效方法。 由於您沒有訪問成員,因此沒有崩潰的原因。
在由空指針指向的對象上調用show
方法被歸類為“未定義行為”,這意味着無論發生什么情況,您都無法判斷C ++是錯誤的,因為錯誤就在您身邊。
未定義的行為意味着編譯器作者無需關心您的不良編程的結果……因此,他們可以隨意忽略這些情況。 通常,未定義的行為被認為是“崩潰”,但這與事實相去甚遠。 未定義行為執行代碼可能會崩潰,可以什么都不做,可以明顯地什么也不做,讓你的程序崩潰以后在完美的罰款代替一個百萬條指令或者甚至可能運行顯然很好,沒有崩潰,在所有的只是默默地破壞你的數據。
C ++語言的一個主要假設是程序員不會犯錯。 在其他語言中,這是不正確的,您會得到“運行時錯誤天使”,該錯誤會在您犯錯時檢查並停止程序...在C ++中,這些檢查被認為過於昂貴,因此您會得到“運行時錯誤天使”如果發生錯誤,“ undefined behavior daemons”將為您帶來樂趣。
這是C ++高度復雜的原因,我認為C ++對於初學者(初學者會犯很多錯誤)是一個非常糟糕的選擇,並且無法通過實驗學習C ++(因為錯誤的后果是不確定的) )。
在您的特定情況下,考慮到編譯器編寫者是懶惰的(對程序員而言這不是一個壞素質),我猜想在x86體系結構上,代碼可能不會造成任何損害,並且可能會執行,就像指針指向有效賓語。 當然,這只是推測,因為它取決於編譯器,硬件和編譯器選項。 可能那里有好的編譯器帶有編譯調試選項,該選項會生成崩潰的代碼。
該行為是不確定的。 程序實際的行為方式取決於實現。 我希望大多數實現都嘗試在不檢查指針的情況下執行代碼。 因此,您的初始示例應平穩運行,因為它沒有引用該類的任何本地成員。
檢查以下代碼的作用很有趣:
class ex
{
int i;
public:
ex(int ii = 0):i(ii){}
~ex(){cout<<"dest"<<endl;}
virtual void show()
{
cout<<"show fun called"<<endl;
}
};
int main(int argc , char *argv[])
{
ex *ob = NULL;
ob->show();
return 0;
}
如果該方法是虛擬的,則運行時可能需要訪問對象的某些本地數據,從而導致空指針或錯誤的地址異常。
編輯
我在cygwin上使用GCC測試了以下稍作修改的示例:
#include <iostream>
using namespace std;
class ex
{
int i;
public:
ex(int ii = 0):i(ii){}
~ex(){cout<<"dest"<<endl;}
void show()
{
cout<<"show fun called"<<endl;
}
virtual void vshow()
{
cout<<"vshow fun called"<<endl;
}
};
int main(int argc , char *argv[])
{
ex *ob = NULL;
ob->show();
ob->vshow();
return 0;
}
實際上,輸出為:
show fun called
Segmentation fault (Core dumped)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.