【C++】 const /const_cast/static(更新中。。。)

用const_cast来去除const限定

对于const变量,我们不能修改它的值,这是这个限定符最直接的表现。但是我们就是想违背它的限定希望修改其内容怎么办呢?

下边的代码显然是达不到目的的:

 const int constant = 10;
int modifier = constant;

因为对modifier的修改并不会影响到constant,这暗示了一点:const_cast转换符也不该用在对象数据上,因为这样的转换得到的两个变量/对象并没有相关性。

只有用指针或者引用,让变量指向同一个地址才是解决方案,可惜下边的代码在C++中也是编译不过的:

 const int constant = 21;
int* modifier = &constant 
// Error: invalid conversion from 'const int*' to 'int*'

(上边的代码在C中是可以编译的,最多会得到一个warning,所在在C中上一步就可以开始对constant里面的数据胡作非为了)

把constant交给非const的引用也是不行的。

const int constant = 21;
int& modifier = constant;
// Error: invalid initialization of reference of type 'int&' from expression of type 'const int'

于是const_cast就出来消灭const,以求引起程序世界的混乱。

下边的代码就顺利编译功过了:

 const int constant = 21;
const int* const_p = &constant;
int* modifier = const_cast<int*>(const_p);
*modifier = 7;

传统转换方式实现const_cast运算符

准转换运算符是可以用传统转换方式实现的。const_cast实现原因就在于C++对于指针的转换是任意的,它不会检查类型,任何指针之间都可以进行互相转换,因此const_cast就可以直接使用显示转换(int*)来代替:

const int constant = 21;
const int* const_p = &constant;
int* modifier = (int*)(const_p);

或者我们还可以把他们合成一个语句,跳过中间变量,用

const int constant = 21;
int* modifier = (int*)(&constant);

替代

const int constant = 21;
int* modifier = const_cast<int*>(&constant);

然而这样就可以改变const了么

int main()
{
 const int s = 7;
 const int * n = &s;
 int * t = const_cast<int *> (n);
 cout << s << endl;
 cout << *t << endl;
 *t = 21;
 cout << "*****************" << endl;
 cout << s << endl;
 cout << *t << endl;
 cout << "*****************" << endl;
 cout << &s << endl;
 cout << t << endl;
 
}
输出:
7
7
*****************
7
21
*****************
0041FE10
0041FE10

相同的地址但结果却不同,相信这样的结果已经改变了你的认知,它是一个未定义的行为。

结论 : 绝对不对const数据进行重新赋值

a)对于const修饰的局部常量而言,g++编译器(不同编译器机制未必相同)会为其分配内存,由于是静态分配而且是局部常量,所以分配在栈中。
b)对代码中直接引用到该常量(即该常量直接作为右值使用)的情况,编译器会将其直接替换成定义时赋的值。这样一来,无论运行期该常量所在内存被如何修改,都不会影响常量的使用。对于取址操作&con_var而言,&con_var整体被当作一个右值,没有被编译器替换成常值,这也是为什么既然编译器还要为const修饰的常量分配内存的原因。(const folding技术在这里被用到)。
c)const只在编译期间保证常量被使用时的不变性,无法保证运行期间的行为。程序员直接修改常量会得到一个编译错误,但是使用间接指针修改内存,只要符合语法则不会得到任何错误和警告。因为编译器无法得知你是有意还是无意的修改,但是既然定义成const,那么程序员就不应当修改它,不然直接使用变量定义好了。
d)c语言中原本没有const关键字,后来为了兼容,引入了const,但是编译器对其的操作与c++中不同。

为什么还要去const呢?
参考下面两个情形:

//使用const_cast去除const限定,以便函数能够接受这个实际参数。
#include <iostream>
using namespace std; 
void Printer (int* val,string seperator = "\n")
{	
	cout << val<< seperator;
} 
int main(void)
 {		
 	const int consatant = 20;	
 	//Printer(consatant);
 	//Error: invalid conversion from 'int' to 'int*'			   	        		
 	Printer(const_cast<int *>(&consatant));	
 		return 0;
}
//我们定义了一个非const的变量,但用带const限定的指针去指向它,
//在某一处我们突然又想修改了,可是我们手上只有指针,
//这时候我们可以去const来修改了。
#include <iostream>
using namespace std; 
int main(void) 
{	
	int variable = 21;
	const int* const_p = &variable;
	int* modifier = const_cast<int*>(const_p);		
	*modifier = 7;
	cout << "variable:" << variable <<endl;	
	return 0;
} 
/**variable:7**/

static

testStatic() {
 static int count = 10;
 //这里的赋值实际上从未被执行过,这个count的初始化在程序装载的时候被执行
 //它的值被放在了全局变量区
 //这个过程发生在main函数被执行之前(和全局变量的初始化类似,在所有程序执行之前已经完成了初始化)
 return count--;
}

int main()
{
 int count = 1;
 for (; count <= 10; count++) {
  cout << "Static Count : " << count << "  ";
  cout << "Main function Conut : " << testStatic() << endl;
 }
 system("pause");
 return 0;
}
输出:
Static Count : 1  Main function Conut : 10
Static Count : 2  Main function Conut : 9
Static Count : 3  Main function Conut : 8
Static Count : 4  Main function Conut : 7
Static Count : 5  Main function Conut : 6
Static Count : 6  Main function Conut : 5
Static Count : 7  Main function Conut : 4
Static Count : 8  Main function Conut : 3
Static Count : 9  Main function Conut : 2
Static Count : 10  Main function Conut : 1

static特性

  • static 变量在程序装载的时候就被初始化,它存在于程序内存空间的静态储存区中而不是堆栈中,这样在下一次被调用的时候它还是保持原来的值
  • 和全局变量不一样,它只在自己的作用范围内可见,但是在可用范围之外它并不会消失(与堆栈和堆中的数据不一样)
  • 它和全局变量最大的不同之处,在于它具有隐藏的功能(全局变量在所有被编译的.c文件中都可见)
  • 静态全局变量、静态局部变量、全局变量都放在内存的静态存储区,局部变量则存在于堆栈区

在程序被装载进内存时,所有定义为 static 的变量已经完成了初始化,并被放在了程序段的全局变量区,所以我们无论定义了多少次这个static的对象,内存中实际存在的变量还是只有这一个。
无论这个static变量在我们看来作用于哪一个范围内,比如一个函数中,函数结束后这个变量依然存在,并不会因为函数结束而被回收。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值