const和非const变量/对象/指针之间的赋值问题

本文详细探讨了const关键字在C++中如何影响变量、对象和指针的赋值行为。const修饰的变量或对象不可修改,导致赋值方向上的差异:const对象不能赋值给非const对象,但反之可以。对于指针,const修饰指针内容或指针本身会产生不同效果,影响赋值的合法性。

const和非const变量/对象/指针之间的赋值问题

变量赋值

const int a = 10;
int b = 10;
a = b;// error
b = a;// correct

变量在经过const关键字修饰以后就不能再被修改了,所以a=b是错误的。而b=a仅仅是将a变量中的内容复制一份给了变量b,所以赋值过后对副本b进行操作是不会对于a有什么影响的,这样行为是合法的。

对象赋值

struct A
{
	int a;
};
const A a;
A b;
a = b;// error
b = a;// correct

对象之间的赋值和变量之间的赋值也是一样的,只不过对象中可能存在的数据更多一点,但是赋值的性质还是和变量赋值是一样的。

指针赋值

int n1, n2, n3;
const int* a = &n1;
int* b = &n2;
int* const c = &n2;
a = b;// correct
b = a;// error
b = c;// correct

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-OECqWkBI-1628693667815)(C:\Users\张昊宇\AppData\Roaming\Typora\typora-user-images\1628693631603.png)]

首先要明确a和c的区别,a中const修饰的是*a,所以a指针指向的内容是不可以被改变的,而c中const修饰的是c本身的指向,所以c的指向是不能被改变的。

a=b,相当于a指向b指向的空间,但是a的指向的内容是不可以被修改的,b的指向是可以修改的,所以这样a的指向不会对b指向的空间造成潜在威胁。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-wWkFBF5F-1628693667817)(C:\Users\张昊宇\AppData\Roaming\Typora\typora-user-images\1628693641545.png)]

b= a,相当于b指向a指向的空间,a的指向的内容是不可以被修改的,b的指向是可以修改的,这时候如果通过b就可以修改a指向的空间中这不允许被修改的内容,这样b指针的指向改变就会对a指向的空间造成潜在的威胁。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-LcFtFY8B-1628693667817)(C:\Users\张昊宇\AppData\Roaming\Typora\typora-user-images\1628693648099.png)]

b=c,相当于b指向c指向的空间,因为c的指向不可以被改变,但是空间的内容是可以被修改的,所以b并没有对c指向的空间造成潜在的威胁。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-NVhL3zsV-1628693667819)(C:\Users\张昊宇\AppData\Roaming\Typora\typora-user-images\1628693654546.png)]

### `const` 变量赋值 `const` 变量的合法性 在 C++ 中,将 `const` 变量赋值 `const` 变量是**合法的**,前提是赋值过程中不涉及直接的指针或引用操作。这是因为赋值操作会创建一个新的副本,而共享原始常量的内存。因此, `const` 变量获得的是原始 `const` 变量的值,而不是其引用或指针。 例如: ```cpp const int a = 10; int b = a; // 合法:b 是 a 的副本,不共享内存 ``` 上述代码中,`b` 获得的是 `a` 的值,而不是对 `a` 的引用或指针,因此不会违反 `const` 限定符的语义[^4]。 --- ### 指针与引用中的限制 虽然直接赋值是合法的,但若尝试通过指针或引用将 `const` 对象赋给 `const` 指针或引用,则会导致编译错误。这是为了防止通过 `const` 指针或引用修改原本是 `const` 的对象。 例如: ```cpp const int a = 10; int* p = &a; // 法:不能将 const int* 赋给 int*,否则可以通过 p 修改 a 的值 [^4] ``` 若确实需要绕过此限制,可以使用类型强制转换(如 `const_cast`),但这可能导致未定义行为,因为修改原本为 `const` 的对象法的。 ```cpp const int a = 10; int* p = const_cast<int*>(&a); *p = 20; // 未定义行为:试图修改 const 对象 [^1] ``` --- ### 编译器优化与常量传播 在某些情况下,编译器可能会对 `const` 变量进行优化,例如常量折叠或不为其分配实际内存空间。当将这样的 `const` 变量赋值 `const` 变量时,实际上是将编译时常量的值复制给目标变量,而不会涉及运行时的内存访问。 例如: ```cpp const int N = 5; int arr[N]; // N 被当作编译时常量使用 [^2] ``` 此时,`N` 可能并未分配实际内存,而是直接在编译时被替换为 `5`。 --- ### 类型安全与赋值规则 C++ 中的类型系统确保了从 `const` 到 `const` 的赋值不会破坏类型安全。 `const` 变量赋值后拥有独立的状态,不会影响原始 `const` 变量。然而,这种赋值并不适用于指针或引用类型,因为它们涉及共享内存,可能引发对 `const` 对象的修改风险。 --- ### 总结 - 将 `const` 变量赋值 `const` 变量是合法的,因为赋值操作创建了副本。 - 指针或引用不可绕过 `const` 限定符,否则会引发编译错误或未定义行为。 - 编译器可能对 `const` 变量进行优化,如不分配实际内存。 - 类型系统确保赋值过程不会破坏类型安全,但指针引用需特别注意。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hyzhang_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值