C++ 我应该使用const_cast吗?

C++ 我应该使用const_cast吗?,c++,C++,我在一个函数中对C字符串进行解析,如下所示: void parse(const char** params, int numParams); char* charPointer; charPointer = params[0]; const bool do_it = true; bool *ptr = const_cast<bool*>(&do_it); *ptr = false; // optimizer probably thinks this is always

我在一个函数中对C字符串进行解析,如下所示:

void parse(const char** params, int numParams);
char* charPointer;
charPointer = params[0];
const bool do_it = true;
bool *ptr = const_cast<bool*>(&do_it);
*ptr = false;

// optimizer probably thinks this is always true
if (do_it) initiate_nuclear_first_strike(); 
我想从params中存储的一个字符串中提取一些信息,所以我编写了如下代码:

void parse(const char** params, int numParams);
char* charPointer;
charPointer = params[0];
const bool do_it = true;
bool *ptr = const_cast<bool*>(&do_it);
*ptr = false;

// optimizer probably thinks this is always true
if (do_it) initiate_nuclear_first_strike(); 
编译器不喜欢这样,告诉我它不能从常量字符*转换为字符*。我理解这背后的原因(理论上,我可以写到charPointer指向的地址,但如果允许的话,我不能写到params[0]指向的地址),但我不理解的是我应该如何绕过它。我知道有两种方法可以修复这个错误,但我不知道哪一种是“正确的”,或者它们之间的区别是什么。第一个是:

const char* charPointer;
charPointer = params[0];
第二种方法是:

char* charPointer;
charPointer = const_cast<char*>(params[0]);
char*charPointer;
charPointer=const_cast(参数[0]);
那么,哪一个更好,为什么

那么,哪一个更好,为什么

当然比使用

char* charPointer;
charPointer = const_cast<char*>(params[0]);
char*charPointer;
charPointer=const_cast(参数[0]);

解析字符数组通常不需要更改它,因此最好将其保持为常量,只有在指针确实指向非常量的情况下才是安全的,所以修改它不是问题。如果该值最初是
const
,则使用
const\u cast
去除该constness,然后写入该值基本上是未定义的行为(例如,代码的其他部分可能假定值没有更改,因此您的修改仅在某些时候生效)

所以一定要使用这个版本:

const char* charPointerr = params[0];
一般来说,如果您需要求助于
const\u cast
,您可能正在做一些事情。。。如果没有错,那么至少丑陋。如果你不确定它是丑陋的还是完全错误的,那么它很可能是错误的


由于以下未定义的行为,可能出现严重错误的示例:

void parse(const char** params, int numParams);
char* charPointer;
charPointer = params[0];
const bool do_it = true;
bool *ptr = const_cast<bool*>(&do_it);
*ptr = false;

// optimizer probably thinks this is always true
if (do_it) initiate_nuclear_first_strike(); 
const bool do_it=true;
bool*ptr=const_cast(&do_it);
*ptr=false;
//优化器可能认为这总是正确的
如果(做它)首先发动核打击();

使用调试构建进行开发时,一切似乎都正常。然后,发布构建被部署(当然,由于匆忙,没有测试),然后爆炸,世界末日。UB就是这样危险的(旁注:UB的效果也可能完全模糊,不像这个例子那么容易理解)。

施放几乎总是一种代码气味。我所发现的
const_cast
的唯一合法用途是将const数据传递给一个传统的库函数,您知道它不会修改数据,但在古代是在没有const说明符的情况下编写的


你为什么要把它扔掉呢?在这种情况下,您不需要这样做。常量正确性是编写正确代码的一大好处。我发现,将不需要更改的所有内容都设置为常量是一件好事。

仅当您设置的变量最初是非常量时,const\u cast才是安全的。例如,如果有一个函数接受常量char*的参数,并传入一个可修改的char*,则可以安全地将该参数转换回char*并进行修改。但是,如果原始变量实际上是const,那么使用const_cast将导致未定义的行为

const char* charPointer = params[0];

是更好的方法,在同一行中初始化和声明也更好。

将指向常量的指针强制转换为指向非常量的指针允许您通过指针写入常量对象

写入常量对象是未定义的行为

C++语言规范非常明确地说明了当调用未定义行为时发生的事情——<强>程序的整个逻辑变得不明确,编译器处于“强>不合理的行为< <强> >的情况下,甚至在程序的不相关部分,也无法对程序的行为进行推理


知道了这一点,再次问自己这个问题。:-)

它是常量。相应地声明指针。不要取消常量,因为它应该是只读的,不要触摸。这就像把椅子上所有的螺丝都拧松,希望它不会散开。很多时候,当你使用石膏时,你做了错事,好吧,但为什么?如果我const_cast,这是否意味着我可以写入该内存地址,即使理论上我不应该这样做?为什么要将声明和初始化拆分到不同的行上
const char*charPointer=params[0]
对我来说已经足够清楚了。C++不要求你在C的一个块的开始时声明所有的东西(C从1999以来就不需要它)。你不应该抛出。甚至更好。常量对象可能会被放入内存的只读区域,所以修改这些对象会给你们一个硬件例外。我同意你们的观点:丢弃常量是危险的,而且通常是错误的。不过,分析并不完全正确。无论转换的指针指向什么,强制转换都是合法的;只有在基础对象可修改的情况下,写入结果指针才有效。在代码段中,分配给
ptr
的行是正确的;下一行不是,明白了。因此,基本上,编译器可能会在假设params[0]指向的地址的值不变的情况下进行优化,这会在我去更改数据时把事情搞砸。@PeteBecker谢谢,澄清了!