根据c ++语法,const int* const p
意味着p指向它并且它的值不能被重写。但是今天我发现如果我这样编码:
void f(const int* const p)
{
char* ch = (char*) p;
int* q = (int*) ch;
(*q) = 3; //I can modify the integer that p points to
}
在这种情况下,关键字“const”将失去它的效果。使用“const”有什么意义吗?
答案 0 :(得分:6)
你在这里抛弃了const
:
char* ch = (char*) p;
实际上,你说的是“我知道我在做什么,忘记你是const
,我接受后果。” C ++允许你做这样的事情,因为有时它可能是有用/必要的。但它充满了危险。
请注意,如果传递给函数的参数确实是const
,那么您的代码将导致未定义的行为(UB)。你无法从函数内部知道。
另请注意,在C ++中,最好使您的意图清晰,
int* pi = const_cast<int*>(p);
这清楚表明你的目的是抛弃const
。它也更容易搜索。关于危险和UB的相同警告适用。
答案 1 :(得分:1)
如果const int* const p
指向编译时常量,那么您的示例会使应用程序崩溃,当您抛弃常量时,您需要确定自己在做什么。
C ++是成人的一种语言,永远不会因为短暂的安全而牺牲额外的力量,代码作者的选择是选择是留在安全区还是使用演员操作员并向C / asm靠近一步。
答案 2 :(得分:0)
C / C ++会让你做很多事情,让你自己“伤害”自己。在这里,抛弃const
p
是“合法的”,因为编译器会假设您知道自己在做什么。这是否是良好的编码风格是另一回事。
当您执行此类操作时,您将承担任何副作用及其可能产生的问题的责任。这里,如果参数中指向的内存是静态内存,程序可能会崩溃。
简而言之,仅仅因为你可以做某事并不意味着这是一个好主意。
答案 3 :(得分:0)
const
关键字是一种使用编译器来捕获编程错误的方法,仅此而已。它没有声明在运行时内存的可变性,只是如果你直接修改值,编译器应该对你大喊大叫(不使用C风格的强制转换)。
C风格的演员阵容几乎就是“我知道我在这里做什么”的标记。在大多数情况下,这是错误的。
答案 4 :(得分:0)
在此处更改指针的类型。使用这样的强制转换(C型)转换,您可以将其更改为任何可能的指针,没有问题。
与使用c ++强制转换的方式相同:const_cast<...>(...)
:
int* p_non_const = const_cast<int*>(p);
在这种情况下(我希望)你会立即看到发生了什么 - 你只是摆脱了常量。
请注意,在您的程序中,您也不需要temprorary变量ch
。你可以直接这样做:
int* q = (int*) p;
原则上你不应该使用这样的演员,因为正确设计和编写的程序不需要它。通常,const_cast用于程序中的快速和临时更改(以检查某些内容)或使用来自某些未正确设计的库中的函数。