2013-09-17 4 views
9

Как с помощью const_cast, если кто-то собирается изменить мой объявленный постоянный объект, то что такое const?Что такое законное использование const_cast

Я имею в виду, как кто-то гарантирует, что то, что он объявил как const, не будет изменен в любом случае ??

+3

Это то же самое, что с 'reinterpret_cast',' union', 'memcpy' и многими другими: всегда есть способ обойти механизмы безопасности на C++, в основном ссылаясь на неопределенное поведение. То, что вы можете их разбить, не означает, что эти механизмы не приносят пользы. – dyp

+1

«То, что он объявил как const, не будет изменен в любом случае?» По соглашению, объект, сконструированный 'const', не изменит свое * наблюдаемое поведение *. Это не значит, что его биты не будут изменены. – dyp

+0

Ленивая оценка (http://stackoverflow.com/questions/881119/dealing-with-lazy-comput-in-c-classes), но, вероятно, использование mutable лучше, чем, например, const_cast <...> (это). – user2672165

ответ

9

Вы правы, использования const_cast часто указывает на недостаток дизайна, или API, который находится вне вашего контроля.

Однако есть исключение, оно полезно в контексте перегруженных функций. Я цитирую пример из книги C++ Primer:

// return a reference to the shorter of two strings 
const string &shorterString(const string &s1, const string &s2) 
{ 
    return s1.size() <= s2.size() ? s1 : s2; 
} 

Эта функция принимает и возвращает ссылки на const string. Мы можем вызывать функцию по парам неконстантных аргументов string, но в результате мы получим ссылку на const string. Возможно, мы захотим иметь версию shorterString, которая при заданных аргументах, отличных от const, дала бы простую ссылку. Мы можем написать эту версию нашей функции с помощью const_cast:

string &shorterString(string &s1, string &s2) 
{ 
    auto &r = shorterString(const_cast<const string&>(s1), 
          const_cast<const string&>(s2)); 
    return const_cast<string&>(r); 
} 

Этой версия вызывает константные версии shorterString литья своих аргументов ссылок на const. Эта функция возвращает ссылку на const string, которую мы знаем связано с одним из наших исходных, неконстантных аргументов. Поэтому мы знаем, что безопасно отбрасывать эту строку обратно на равную string& в обратном направлении.

+0

Я хотел бы отметить, что этот пример плохо иллюстрируется тем, что ** добавление ** квалификатор 'const' не требует приведения. Так что только один действительно нужен (последний). –

+0

@ MatthieuM. Без добавления добавок const вы получите бесконечную рекурсию. – Angew

+0

@Angew: Я не имел в виду, что добавление 'const' было бесполезным, я имел в виду, что использование' const_cast' для добавления было излишним. Например, вы можете использовать [static_cast] (http://ideone.com/tvhMkf) для того же эффекта. –

2

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

Отбрасывание части const, а затем изменение данных, несомненно, приведет к неопределенному поведению.

7

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

This question относится.

Кроме того, на странице MSDN говорит (курсив мой):

Указатель на любой тип объекта или указатель элемента данных может быть явно преобразован к типу, который является идентичным для сопзЬ, за исключением, летучий , и __автоматизированные квалификаторы. Для указателей и ссылок результат будет ссылаться на исходный объект. Для указателей на члены данных результат будет относиться к тому же члену, что и исходный (uncast) указатель на элемент данных. В зависимости от типа ссылочного объекта операция записи через результирующий указатель, ссылку или указатель на элемент данных может приводить к неопределенному поведению. Вы не можете использовать оператор const_cast для прямого переопределения постоянного состояния постоянной переменной.

+0

Я думал, что non-const для const был upcast и не нуждался в явном приведении? –

+0

@JanDvorak Для некоторых преобразований указателя требуется, например, от 'int **' до 'int const **'. – dyp

+0

Другой момент: вы можете безопасно удалить 'const' из любого объекта, который не был объявлен' const'. 'int i; int const * p = & i; int * pp = const_cast (p); * pp = 42; 'безопасно. – dyp

4

Никто не может изменять ваш постоянный объект с помощью const_cast или без него. const_cast не позволяет изменять постоянные объекты.

Когда дело доходит до удаления константности, цель const_cast, чтобы позволить вам удалить константность из пути доступа (указатель или ссылка), что приводит к не -постоянному объекту.

Например

int i = 5; 
const int *p = &i; 

*const_cast<int *>(p) = 10; 
assert(i == 10); 

В приведенной выше коде const_cast используются для получения модифицирующего доступа к объекту через указатель ip. Объект i не является константой, поэтому нет ничего плохого в этой модификации.

Это цель const_cast. Его также можно использовать для противоположной цели: добавление константы к указателю или ссылочному типу. Но «изменение постоянных объектов» не то, что вы можете сделать с const_cast. Постоянные объекты не изменяются.

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