簡體   English   中英

在cv限定詞是唯一區別的指針類型之間進行轉換的規則

[英]Rules for converting between pointer types where cv-qualifiers are the only difference

這個問題專門與C ++ 98有關,但是如果您願意的話,可以隨意提供任何有用的信息,無論是否有更新的標准。

如果您知道答案並想跳過其余的內容,則簡短而優美的是:

int **w;
int volatile*     *x = w; // error
int volatile*const*y = w; // OK
int const   *const*z = w; // OK    

為什么在聲明y需要在volatile權利上使用const 如果允許使用x的聲明,某人可能會完成什么邪惡的事情?

在標准的第4.4.4節中,它表示:

轉換可以在除多級指針中的第一個之外的其他級別上添加cv限定詞,但要遵守以下規則:

如果存在類型T並且整數n > 0,則兩個指針類型T1和T2 相似 ,從而:

  • T1為CV10 ptr至CV11 ptr至... CV1N T
  • T2是CV20 ptr到CV21 ptr到... CV2N T

...每個CVij是const,volatile,const volatile或什么都不是。 指針類型中第一個的cv限定詞(例如,指針類型T1中的CV11,CV12,...,CV1N) 之后的n個元組稱為指針類型的cv限定符 類型T1的表達式可被轉換當且僅當滿足以下條件鍵入T2:

  1. 指針類型相似
  2. 對於每個j > 0,如果const在CV1j中,則const在CV2j中,對於volatile同樣。
  3. 如果CV1j和CV2j不同,則const在每個CV2k中為0 <k <j

......在這之后接着舉一個例子用於分配**const** 以上是我的重點 ,斜體來自文檔。

將其放入代碼中:

 int CV13* CV12* CV11* CV10 b1;
 int CV23* CV22* CV21* CV20 b2 = b1;

我對某些細節有些模糊...所以這是一些問題或可能存在缺陷的觀察結果:

1)它說的at levels other than the first 對此不再CV20 ,但是CV20可以是任何有效的CV限定詞。

2)底部的第三條規則說,如果T2在級別j處添加constvolatile ,則級別1 ... j-1必須為const(否則會發怒)。 以下,星號與頂部的星號有所不同,以強調第三條規則的含義:

int *****w;
int **volatile*     *     *x = w; // error
int **volatile*const*const*y = w; // OK
int **const   *const*const*z = w; // OK

我了解為什么z需要它,但為什么要使用y 這大致是4.4.4中的示例,針對易失性情況進行了修改:

void f( int **x ) {
  int volatile**y = x; // not allowed
  // do some evil here
}

什么邪惡可以放在那里?

(注意:“此問題專門與C ++ 98有關”,但是在過去和現在的所有版本標准中,事務的狀態都是相同的(我敢打賭,將來也是如此),因為它本質上是關於const正確性和防止編碼器在類型系統中打個洞。)

由於該標准使用通用術語“ cv-qualifiers ”,因此我發現僅使用“ const ”(不使用“ volatile ”)進行推理時會更容易理解[但是請參見下文中有關volatile的示例] “ C ++ FAQ Lite”具有一個相關條目: 為什么在轉換Foo**Foo const**出錯?

本質上,允許進行轉換將使您無提示地修改const T(通過指向 -const T的指針):

int const theAnswer = 42;
int* p = 0;  // int* p = &theAnswer; is not allowed of course...
int** pp = &p;
int const** ppc = pp;  // <-- Error, but imagine this were allowed...
*ppc = &theAnswer;  // &theAnswer is `int const*` and *ppc is `int const*` too,
                    // but it's also doing *pp = &theAnswer; i.e. p = &theAnswer;
*p = 999;  // I.e. theAnswer = 999; => modifying a const int!

但是通過添加一個“第一級” const ,轉換為int const* const* pcpc = pp; 之所以有效,是因為編譯器會阻止您執行*pcpc = &theAnswer; 之后(因為*pcpcconst )。


編輯:對於volatile ,問題也許比用不太明顯的const ,但允許轉換會讓你默默不正確的訪問(讀取或寫入) 揮發性 T作為如果沒有揮發物(通過一個指向 -volatile T) :

extern int volatile externTimer;
int* p = 0;  // int* p = &externTimer; is not allowed...
int** pp = &p;
int volatile** ppv = pp;  // <-- Error, but imagine this were allowed...
*ppv = &externTimer;  // &externTimer is `int volatile*` and *ppv too,
                      // but it's also doing *pp = &externTimer; i.e. p = &externTimer;
int a1 = externTimer;  // First read
int a2 = externTimer;  // Second read, mandatory: the value may have changed externally
int b1 = *p;  // First read
int b2 = *p;  // Second read? may be optimized out! because *p is not volatile

但是通過添加一個“第一級” const ,轉換int volatile* const* pcpv = pp; 是有效的,因為編譯器將阻止您執行*pcpv = &externTimer; 之后(因為*pcpvconst )。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM