2016-03-18 2 views
1

Так что я делаю некоторые синтаксический разбор C-строки в функции, которая выглядит следующим образом:Должен ли я использовать const_cast?

void parse(const char** params, int numParams); 

Я хотел вытащить информацию из одной из строк, хранящихся в Params, так что я написал код, который выглядел как это:

char* charPointer; 
charPointer = params[0]; 

компилятор не нравится это и сказал мне, что он не может конвертировать константный символ * к * полукокса. Я понимаю причины этого (теоретически я мог бы написать адрес, на который указывает charPointer, но не по параметрам [0], если он позволил мне), но я не понимаю, как мне обойти это. Я знаю два способа исправить эту ошибку, но я не знаю, какая из них «правильная» или действительно какая разница между ними. Первый:

const char* charPointer; 
charPointer = params[0]; 

И второй способ:

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

Так что лучше и почему?

+3

Это 'const'. Объявите указатель соответствующим образом. Не отключайте его, потому что он должен быть доступен только для чтения, не трогайте его. Это похоже на то, чтобы закрутить все болты на вашем стуле и надеяться, что он не развалится. – tadman

+0

Довольно часто, когда вы получаете возможность использовать броски, вы делаете что-то неправильно –

+0

Хорошо, но почему? Если я const_cast, это значит, что я могу писать на этот адрес памяти, хотя теоретически я не мог бы этого сделать? – quiggy

ответ

4

const_cast безопасен только в том случае, если указатель действительно указывает на то, что не является константой, поэтому его изменение не является проблемой. Если значение изначально const, то с помощью const_cast, чтобы избавиться от константы, а затем записать в него в основном неопределенное поведение (например, другие части кода могут предполагать, что значение не изменяется, поэтому иногда ваша модификация вступает в силу).

Так определенно использовать эту версию:

const char* charPointerr = params[0]; 

В общем, если вам нужно прибегать к const_cast, вы, вероятно, делать что-то ... если не так, то, по крайней мере, некрасиво. И если вы не уверены, что это просто уродливо или совершенно неправильно, то это, вероятно, неправильно.


Пример чего-то где-то может пойти наперекосяк из-за неопределенное поведение, как это:

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(); 

При разработке с помощью отладки сборки, все, кажется, работает. Затем развертывание сборки развертывается (без тестирования, конечно, потому что в спешке) и BOOM, конец света. UB опасен (примечание: эффекты UB также могут быть совершенно неясными и не так легко понятными, как этот пример).

+1

Еще лучше. const объекты могут быть помещены в области памяти только для чтения, поэтому их изменение даст вам аппаратное исключение. – SergeyA

+1

Я согласен с вашей точкой зрения, что изгнание const опасно и обычно неправильно.Однако анализ не совсем прав. Бросок законен независимо от того, к чему обращается указатель; ** запись ** через полученный указатель действительна только в том случае, если базовый объект модифицируется. В фрагменте кода строка, которая назначает 'ptr', прекрасна; это следующая строка, которой нет. –

+1

Получил. Таким образом, в основном компилятор может оптимизировать, полагая, что значение в адресе, на которое указывает параметр [0], не изменяется, что заставляет меня заходить и менять эти данные. – quiggy

4

Итак, что лучше и почему?

const char* charPointer; 
charPointer = params[0]; 

, безусловно, лучше, чем принудительно удаление ограничения с помощью

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

Синтаксического массива символов, как правило, не нужно, чтобы изменить его, таким образом, его лучше оставить его const.

1

Кастинг почти всегда является запахом кода.Единственное законное использование, которое я когда-либо нашел для const_cast, - это передать данные const в устаревшую библиотечную функцию, которая, как вы знаете, не будет изменять данные, но была написана в древние времена без спецификатора const.

Почему бы вам не отбросить его? В этом случае вам не нужно. Корректность Константа - великое благо для написания правильного кода. Я обнаружил, что сделать все, что не нужно, чтобы изменить, - это хорошо.

1

const_cast является безопасным, только если вы производите переменную, которая изначально была непостоянной. Например, если у вас есть функция, которая принимает параметр const char *, и вы передаете измененный символ *, это безопасно для const_cast, чтобы этот параметр возвращался к char * и изменял его. Однако, если исходная переменная была фактически сопзЬ, то с помощью const_cast приведет к непредсказуемому поведению

const char* charPointer = params[0]; 

это лучший способ сделать это, а также лучше инициализировать и объявить в одной и той же линии.

1

Приведение указателя на константу в указатель на не-const позволяет писать постоянным объектам через указатель.

Запись в постоянные объекты undefined поведение.

++ язык спецификации C очень четко о том, что происходит, когда вы вызываете неопределенное поведение - вся логика программы становится неопределенным, компилятор под не обязаны вести себя разумно, и это становится невозможно причине о том, как программа будет вести себя - вообще - даже в несвязанных частях программы.

Зная это, задайте себе вопрос снова. :-)

Смежные вопросы