簡體   English   中英

為什么“具有const成員的結構”類型的指針不能指向“具有非const成員的結構”?

[英]Why can't a pointer of a “struct with const member” type point to a “struct with non-const member”?

該代碼無法編譯:

struct s_t {
    int a;
};

struct c_s_t {
    const int a;
};

s_t s;
c_s_t *c_s = &s;
ibug@ubuntu:~ $ g++ -fsyntax-only t.cpp
t.cpp:10:15: error: cannot convert ‘s_t*’ to ‘c_s_t*’ in initialization
 c_s_t *c_s = &s;
               ^

但是,此代碼可以完美地編譯:

int a, *pa = &a, **ppa = &pa, ***pppa = &ppa;
const int * const * const * const cpcpcpa = pppa;

我知道在任何級別上具有更高CV資格的指針都可以指向在任何級別上具有更低CV資格的對象,但是為什么結構不一樣?


上面的問題陳述是一個更復雜問題的MCVE,其中我的朋友正在嘗試在t_s_t<T>t_s_t<const T>之間轉換指針,其中t_s_t是具有一個模板參數typename的模板結構類型,而T是一個任意類型。

原因是s_tc_s_t是不同的類型。

即使將c_s_t定義為:

struct c_s_t {
    int a; // <-- non-const!
};

然后:

s_t s;
c_s_t *c_s = &s;

它仍然無法正常工作。

類型錯誤是您的問題,您只是在嘗試分配錯誤的類型。

這將工作:

s_t s;
s_t *c_s = &s; //types are matching

這兩個是不同的結構,它們是不可轉換的。 它們具有相同的成員這一事實無關緊要,即使您從c_s_t刪除了const ,它也不會改變任何東西。

您的其他示例之所以有效,是因為您將修飾符應用於一種類型。 例如,這是完全合法的:

struct s_t {
    int a;
};

s_t s;
const s_t const* cs = &s;

我了解在任何級別上具有更高CV資格的指針都可以指向在任何級別上具有較低CV資格的對象

這實際上是不對的,至少不是您所描述的那樣。 只能任意添加最高的CV限定詞(當然,指針本身也可以添加CV限定詞!),在C和C ++中都是這種情況。

這是“任何級別”概念的反例,直接取自當前標准草案的[conv.qual/3]

[注意:如果程序可以將類型T**的指針分配給類型const T**的指針(也就是說,如果允許下面的第1行),則程序可能會無意中修改const對象(這樣做就可以了)在第2行)。 例如,

 int main() { const char c = 'c'; char* pc; const char** pcc = &pc; // #1: not allowed *pcc = &c; *pc = 'C'; // #2: modifies a const object } 

—尾注]

無論如何,然后您會問:

但是為什么結構不一樣呢?

當然,您可以將const T*指向T ,但這不是您要做的。 此規則不適用於遞歸。 類可以容納一個以上的成員,因此您的方法通常無法正常使用(單成員類不需要特殊的規則)。

在這種情況下,這兩個類在布局上是兼容的,因此我希望reinterpret_cast在大多數情況下都起作用:

struct s_t {
    int a;
};

struct c_s_t {
    const int a;
};

int main()
{
   s_t s;
   c_s_t *c_s = reinterpret_cast<c_s_t*>(&s);
}

現場演示

但是,似乎在布局兼容性優點上的別名實際上定義不明確,因此最終最好還是重新考慮設計。

tl; dr:不同的類型是不同的類型。

暫無
暫無

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

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