/**内存空间来理解const to non-const or non-const to const**/
int main()
{
const int a(4);//a编译时是开辟在常量存储区的
int b = a;//OK,b开辟在栈区,只是一个拷贝,互不影响
//----------reference--------//
//-------const to non-const reference
const int a1(4);//我们把焦点放在主体上,开辟在常量区,值不可变
int &b1 = a1;//error没有开辟空间,只是a1的一个小名,此时编译器禁止这种行为,因为若允许这么做了之后,就有试图通过b1来改变a1值的嫌疑,所以编译器禁止这么做
//non-const to const reference
int a2(4);//a2 的值可变,开辟在栈上,记住是栈上
const int &b2 = a2;//OK,b2是a2的别名,加const修饰只是说明,通过b2是不可以修改a2的,但是我们栈上的变量是可以改变的
a2 = 5;//OK 所以这句是对的
//--------------pointer---------//
//-------const to non-const pointer
int a3(4);//值可变,开辟在栈上
const int *p = &a3;//加const修饰,只是说明通过这个指针不能改变它所指向的值,也就是通过p你不能改变a3
int *p1 = p;//error这里和引用相似,编译器禁止这种行为,因为如果允许这么做,那么就有试图通过p1来改变p所指向的变量的值。
p1 = &a3;//OK 常规将地址赋值给指针变量
//-------non-const to const pointer
int *p2 = &a3;
const int *p3 = p2;//OK 加const修饰只是说明通过p3不能修改它所指向的变量的值
a3 = 5;//OK,栈上的变量值可变
return 0;
}
所以我们一定要认清楚本体是开辟在哪里的,如果是开辟在常量区,那么他就是不可改变的,如果是开辟在栈区,那么他就是可以改变的,那么此时对于指向本体的指针,或绑定在本体上的引用前面加上const修饰,只是说明通过此指针或者引用不可以改变本体的值而已,并不是说他们绑定的对象的值不可以改变。[/
10 个解决方案
#1
const int a(4);并非意味着a在常量区。作为编译器保证的一个所谓“常量”并不是说将a安排在常量区来达到这个目的的。虽然编译器对a会做优化,但不是将其放置常量区这样的操作。当然具体编译器的做法可以google“常量折叠”。
#2
版主给吧加精吧,鉴于这么多人问const 的问题,我呕心沥血发表一作,沉了就太对不起我了
#3
#4
那具体是开辟在哪里的?
#5
如果你用volatile来限制这个优化,你就知道和普通变量一样了。在什么地方定义就在相应的存储区域开辟存储空间。优化做了什么请google“常量折叠”
#6
还是在栈上。
#7
NND,5楼不见了。算了再打一次,你用volatile限制这个优化,然后就知道const 修饰的变量在哪定义就在相应的存储区域分配内存。更多时候我都回答是const修饰的变量。而不会将其等价于常量。
#8
得了,我结贴,趁没有误人子弟之前,赶紧结吧,有些概念模糊了
#9
谢了
#10
谢了
#1
const int a(4);并非意味着a在常量区。作为编译器保证的一个所谓“常量”并不是说将a安排在常量区来达到这个目的的。虽然编译器对a会做优化,但不是将其放置常量区这样的操作。当然具体编译器的做法可以google“常量折叠”。
#2
版主给吧加精吧,鉴于这么多人问const 的问题,我呕心沥血发表一作,沉了就太对不起我了
#3
#4
那具体是开辟在哪里的?
#5
如果你用volatile来限制这个优化,你就知道和普通变量一样了。在什么地方定义就在相应的存储区域开辟存储空间。优化做了什么请google“常量折叠”
#6
还是在栈上。
#7
NND,5楼不见了。算了再打一次,你用volatile限制这个优化,然后就知道const 修饰的变量在哪定义就在相应的存储区域分配内存。更多时候我都回答是const修饰的变量。而不会将其等价于常量。
#8
得了,我结贴,趁没有误人子弟之前,赶紧结吧,有些概念模糊了
#9
谢了
#10
谢了