您好,登錄后才能下訂單哦!
本篇內(nèi)容主要講解“C++中為什么不要解引用無(wú)效指針”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“C++中為什么不要解引用無(wú)效指針”吧!
ES.65:不要解引用無(wú)效指針
解引用例如null等無(wú)效指針,是無(wú)定義的行為,通常會(huì)立即導(dǎo)致程序崩潰,錯(cuò)誤的結(jié)果,或者內(nèi)存破壞。
Note(注意)
本規(guī)則顯而易見(jiàn)而且眾所周知,但卻很難遵守。它會(huì)帶來(lái)好的代碼風(fēng)格,更充分的庫(kù)支持,不需要很大代價(jià)但可以排除違反的靜態(tài)解析。這是關(guān)于C++類型和資源安全模型的論述的重要組成部分。
See also:(參見(jiàn))
Use RAII to avoid lifetime problems.
使用RAII避免生命周期問(wèn)題。
Use unique_ptr to avoid lifetime problems.
使用unique_ptr避免生命周期問(wèn)題
Use shared_ptr to avoid lifetime problems.
使用shared_ptr避免生命周期問(wèn)題
Use references when nullptr isn't a possibility.
如果不可能出現(xiàn)空指針,使用引用
Use not_null to catch unexpected nullptr early.
使用not_null盡早捕獲意外的空指針。
Use the bounds profile to avoid range errors.
使用邊界規(guī)則群組避免范圍錯(cuò)誤。
Example(示例)
void f()
{
int x = 0;
int* p = &x;
if (condition()) {
int y = 0;
p = &y;
} // invalidates p
*p = 42; // BAD, p might be invalid if the branch was taken
}
為了解決這個(gè)問(wèn)題,要么擴(kuò)展對(duì)象指針意圖指向的對(duì)象的生命周期,要么縮短指針的生命周期(將解引用操作移到所指向?qū)ο蟮纳芷诮Y(jié)束之前。)
void f1()
{
int x = 0;
int* p = &x;
int y = 0;
if (condition()) {
p = &y;
}
*p = 42; // OK, p points to x or y and both are still in scope
}
Unfortunately, most invalid pointer problems are harder to spot and harder to fix.
不幸的是,大多數(shù)無(wú)效指針問(wèn)題難于發(fā)現(xiàn),也難于修改。
Example(示例)
void f(int* p)
{
int x = *p; // BAD: how do we know that p is valid?
}
這樣的代碼大量存在。在經(jīng)歷了大量測(cè)試之后,大部分情況下可以動(dòng)作,但是如果只看局部很難判斷一個(gè)指針有沒(méi)有可能為空。因此,空指針也是錯(cuò)誤的主要來(lái)源之一。存在很多方法可以處理這個(gè)潛在問(wèn)題:
void f1(int* p) // deal with nullptr
{
if (!p) {
// deal with nullptr (allocate, return, throw, make p point to something, whatever
}
int x = *p;
}
There are two potential problems with testing for nullptr:
檢查指針是否為空會(huì)有兩個(gè)潛在問(wèn)題:
it is not always obvious what to do what to do if we find nullptr
在發(fā)現(xiàn)了空指針時(shí)應(yīng)該做什么并不總是很明確。
the test can be redundant and/or relatively expensive
檢查可能是多余的而且/或者代價(jià)相當(dāng)高。
it is not obvious if the test is to protect against a violation or part of the required logic.
很難判斷這個(gè)檢查只是為了防止違反還是必要邏輯的一部分。
void f2(int* p) // state that p is not supposed to be nullptr
{
assert(p);
int x = *p;
}
這種做法只在斷言檢查有效時(shí)需要付出一定的代價(jià),同時(shí)可以為編譯器/解析器提供有用信息。如果C++得到協(xié)議(contracts)的直接支持的話,效果會(huì)更好:
void f3(int* p) // state that p is not supposed to be nullptr
[[expects: p]]
{
int x = *p;
}
Alternatively, we could use gsl::not_null to ensure that p is not the nullptr.
另外,我們可以使用gsl::not_null來(lái)保證p不是空指針。
void f(not_null<int*> p)
{
int x = *p;
}
These remedies take care of nullptr only. Remember that there are other ways of getting an invalid pointer.
這個(gè)改進(jìn)只處理空指針。別忘了還有其他形式的無(wú)效指針。
Example(示例)
void f(int* p) // old code, doesn't use owner
{
delete p;
}
void g() // old code: uses naked new
{
auto q = new int{7};
f(q);
int x = *q; // BAD: dereferences invalid pointer
}
void f()
{
vector<int> v(10);
int* p = &v[5];
v.push_back(99); // could reallocate v's elements
int x = *p; // BAD: dereferences potentially invalid pointer
}
This rule is part of the lifetime safety profile
本規(guī)則是生命周期規(guī)則群組的一部分
Flag a dereference of a pointer that points to an object that has gone out of scope
如果指針指向的對(duì)象已經(jīng)處于生命周期之外,標(biāo)記它的解引用操作。
Flag a dereference of a pointer that may have been invalidated by assigning a nullptr
如果指針由于被設(shè)為空指針而無(wú)效時(shí),標(biāo)記它的解引用操作。
Flag a dereference of a pointer that may have been invalidated by a delete
如果由于指針指向的對(duì)象被銷毀而無(wú)效時(shí),標(biāo)記它的解引用操作。
Flag a dereference to a pointer to a container element that may have been invalidated by dereference
如果指針指向的容器元素由于解引用而無(wú)效時(shí),標(biāo)記它的解引用操作。
到此,相信大家對(duì)“C++中為什么不要解引用無(wú)效指針”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。