开发者

Why does this occur?

Given the following code:

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;

    Te开发者_开发问答mp1.Function();
    Temp2 = Temp1;
}

Produces the following:

B

M

Even though ItemCopy is const. Why am I permitted to indirectly modify it or even take a non-const copy of the pointer?


Because ItemCopy is const, ItemCopy.Ptr has and effective type of char * const. The pointer is const but the item pointed to can be modified. This means that the assignment:

*ItemCopy.Ptr = 'M';

is meaningful and allowed (the underlying object is not itself const), it is also legal to copy the pointer and assign through it as you have done. A direct assignment ItemCopy.Temp = 'M' would not be legal but that doesn't meant that you can't modify the variable ItemCopy.Temp if there is another non-const access path as you have.


Ptr points to ItemCopy.Ptr, which in turn points to Temp. So when you dereference it, you'll be writing to Temp.


Pointer aliasing. By assigning ItemCopy::Ptr to this->Ptr you alias the pointer and through it assign to the other value. Also remember the rule of 3 when writing things like this.


The semantics of:

    const TestA &ItemCopy

can only guarantee the pointer member ItemCopy.Temp itself cannot be directly modified, what the pointer points to is not guaranteed to be const.


It's because const rules are applied at compile time, but this circumvention of it is a result of runtime state. Making a non-const copy of a member of a const referenced object does not modify the object and thus does not violate the const reference. This is because as far as the compiler knows, all you have done is made a copy of a value, the address of a piece of mememory. It does not predict that you might dereference it here or elsewhere - it does not apply constness to memory locations, but to identifiers, and you have not violated that yet.

At runtime, you assign the non-const ptr an address that also happens to be referenced by a const identifier, but there is no compile time connection between the two, because the constness only applies to one of the ways to access it, and even then, only in the scope of this one function. It can't treat your non-const pointer as const in some cases and non-const in others based on runtime state, that would violate the semantics of C++ in other ways.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜