簡體   English   中英

為什么會這樣?

[英]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訪問路徑,你有。

指針別名。 通過將ItemCopy::Ptr分配給this->Ptr您可以對指針進行別名,並通過它指定另一個值。 在寫這樣的東西時還要記住3規則

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.

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