使用指针更改常量对象的值
Changing value of constant object with pointer
有这样的代码:
#include <iostream>
int main(){
const int a = 2;
int* ptr = (int*)&a;
*ptr = 3;
std::cout << &a << " " << ptr << " " << a << " " << *ptr << std::endl;
return 0;
}
结果:
0xbf88d51c 0xbf88d51c 2 3
为什么这两个值不同?这里发生了什么?
int* ptr = (int*)&a;
这是危险的(尽管这本身不会调用UB(。但是,
*ptr = 3;
这会调用未定义行为(UB(,因为您正试图修改ptr
指向的const
对象。UB意味着任何事情都可能发生。请注意,a
实际上是一个常量对象。
§7.1.5.1/4(C++03(说,
除了任何声明为可变的类成员(7.1.1(都可以修改外,在const对象的生存期(3.8(内任何修改const对象都会导致未定义的行为
[Example:
[...]
const int* ciq = new const int (3); // initialized as required
int* iq = const_cast<int*>(ciq); // cast required
*iq = 4; // undefined: modifies a const object
不要这样做。这是未定义的行为。
如果你对编译器撒谎,它会得到它的报复(c(
我有一个尚未测试的假设:
编译器为(0xbf88d51c(留出一个地址,并用2填充。int*ptr被设置为该地址,*ptr=3将3放在该地址。所以*ptr现在指向一个3。但是当它遇到值a时,编译器会硬编码"2",就像你说的是#define a 2
一样。
一种验证方法是提取生成的程序集代码。
顺便说一句,我知道这是未定义的行为,但那又怎样?OP询问为什么会发生这种情况。
... " " << 2 << " " ...
替换了... " " << a << " " ...
。
这样做是为了避免从内存中读取a
的值,因为它已经是已知的、常量并且可以直接添加到汇编指令中。
相关文章:
- 代理对象的常量正确性
- 返回常量对象引用 (getter) 和仅返回字符串有什么区别?
- 如何使用数据对象上的常量指针初始化类
- 为什么C++在将一个对象复制到另一个对象时需要对这两个对象进行低级常量限定
- 为什么当我们有常量引用时创建临时对象?
- 是否可以使用非常量指针调用非常量函数,以及当两个unique_ptrs指向同一个对象时程序的行为方式?
- C++,如何使用常量对象和非常量对象进行比较?
- 通过从构造函数中的'this'复制的指针改变常量对象
- 为什么我可以改变常量对象中的成员变量,这是返回常量对象函数的结果?
- C++将常量字符* 指针数组传递给对象
- C++ 对非常量对象的常量引用和对非常量对象的非常量引用之间的区别
- 未定义的对象(〔basic.life〕/8):为什么允许引用重新绑定(和常量修改)
- 当类具有常量时,将对象插入到向量中
- 算法不适用于非常量对象的const_iterator
- C++:允许临时对象调用非常量成员函数的设计理念是什么?
- 为什么MSVC14允许声明指向动态未初始化常量对象的指针
- 可作为常量调用的比较对象
- C++中的常量对象或私有/常量数据成员(变量)?
- 将值从指针复制到常量对象参数
- 如何正确组合可变对象常量