[英]Why does this occur?
給出以下代碼:
class TestA
{
private:
char Temp;
public:
char *Ptr;
TestA(){Ptr = NULL; Temp = 'A'; Ptr = &Temp;}
void Function(){Ptr = &Temp; Temp = 'B';}
void operator=(const TestA &ItemCopy)
{
//ItemCopy.Temp = 'N'; //Not permitted
printf("%c!\n",ItemCopy.Temp);
Ptr = ItemCopy.Ptr; //This is okay
*Ptr = 'M'; //This is okay, but it re-assigns ItemCopy.Temp. What?
printf("%c!\n",ItemCopy.Temp);
}
};
int main()
{
TestA Temp1,Temp2;
Temp1.Function();
Temp2 = Temp1;
}
產生以下內容:
乙
中號
即使ItemCopy是常量。 為什么我被允許間接修改它甚至采用指針的非常量副本?
因為ItemCopy
是const, ItemCopy.Ptr
具有char * const
有效類型。 指針是const,但可以修改指向的項目。 這意味着分配:
*ItemCopy.Ptr = 'M';
是有意義的和允許的(底層對象本身不是const
),復制指針並通過它完成分配也是合法的。 直接分配ItemCopy.Temp = 'M'
不會是合法的,但是這並不意味着你不能修改變量ItemCopy.Temp
如果有另一個非const
訪問路徑,你有。
Ptr
指向ItemCopy.Ptr
,后者又指向Temp
。 因此,當你取消引用它時,你將寫入Temp
。
語義:
const TestA &ItemCopy
只能保證指針成員ItemCopy.Temp本身不能直接修改,指針指向的內容不保證是const。
這是因為const
規則是在編譯時應用的,但是這種規避是運行時狀態的結果。 制作const引用對象成員的非常量副本不會修改對象,因此不會違反const引用。 這是因為只要編譯器知道,你所做的就是制作一個值的副本,即一段記憶的地址。 它不會預測您可能會在此處或其他地方取消引用它 - 它不會將constness應用於內存位置,而是應用於標識符,並且您尚未違反。
在運行時,您為非const ptr分配一個也恰好由const標識符引用的地址,但兩者之間沒有編譯時連接,因為constness僅適用於訪問它的其中一種方式,甚至那么,只在這一功能的范圍內。 在某些情況下,它不能將非const指針視為const,而在其他情況下則不能將非const指針視為基於運行時狀態的其他指針,這會以其他方式違反C ++的語義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.