const指针为何可重赋值?const成员函数修改类成员问题答疑
问题1:const int* const GetXP3()const这类const成员函数为何能修改类成员?
const成员函数的核心规则是:函数内部不能修改类的成员变量本身,但这里的“成员变量本身”需要结合类型具体分析:
你的Entity类中,X_p是int*类型的成员变量。在const成员函数里,this指针会被限定为const Entity*,因此X_p会被视为int* const——也就是指针本身的存储地址不能被修改(比如不能写X_p = new int(10)),但指针指向的内存内容不受const成员函数的约束。
所以*X_p = 234是修改指针指向的int值,而非修改X_p这个指针变量本身,完全符合const成员函数的规则,因此编译可以通过。
问题2:为何带const限制的返回指针,在main中能被修改?
你遇到的困惑源于对指针返回值的const修饰位置和变量赋值后的const属性理解偏差,逐个拆解说明:
1. const int* GetXP()的情况
const int*表示指针指向的int值不可通过该指针修改,你在main中写*a = 234,理论上应该触发编译错误(因为a是const int*,*a属于const int,不能被赋值)。如果你的代码没有报错,大概率是编译器未开启严格语法检查(比如未启用-Wall或-Werror参数)。
而a = nullptr是合法的:因为const int*的const仅限制指向的内容,指针本身是可以被重新赋值的,这和函数注释描述一致。
2. int* const GetXP2()的情况
int* const表示指针本身不可被修改,但这个const限制只针对返回的临时指针对象——你不能直接对返回值执行GetXP2() = nullptr这类操作,但当你把它赋值给int* b时,只是将指针的地址值复制给了新的普通指针b,b本身不受原返回值的const限制,所以b = nullptr是合法的。
*b = 234合法,是因为int* const允许修改指向的内容,这也符合函数注释的描述。
3. const int* const GetXP3()const的情况
这个返回值表示指针本身不可修改,且指向的内容也不可修改,但和第一个情况类似:*c = 32理论上应该编译报错,因为c是const int*,不能通过它修改指向的内容。如果实际未报错,同样是编译器检查不严格的问题。
c = nullptr合法,是因为你把返回的const int* const赋值给了const int* c,c本身是普通的指针变量(仅限制指向内容),所以可以重新赋值。
附完整代码参考:
Entity类代码
class Entity { private: int* X_p = nullptr; int* Y_p = nullptr; public: // 返回可重赋值但指向值不可修改的指针 const int* GetXP() { return X_p; } // 返回不可重赋值但指向内容可修改的const指针 int* const GetXP2() { return X_p; } // 返回指针本身不可修改、指向内容也不可修改的指针,且函数不可修改类成员 const int* const GetXP3()const { *X_p =234; // 合法:修改的是指针指向的内容,而非指针本身 return X_p; } };
main函数代码(标注理论上的错误点)
const int* a = GetXP(); *a = 234; // 理论编译错误:不能修改const int*指向的内容 a = nullptr; // 合法:const int*本身可重赋值 int* b = GetXP2(); *b = 234; // 合法:int* const允许修改指向内容 b = nullptr; // 合法:赋值给普通指针后,指针本身可修改 const int* c = GetXP3(); *c = 32; // 理论编译错误:不能修改const int*指向的内容 c = nullptr; // 合法:const int*本身可重赋值
内容的提问来源于stack exchange,提问作者zen

