Qt-QList const корректность
A QList<T *> не может легко быть const-правильным. Рассмотрим функцию
void f(QList<T *> list)
{
list[0]->constFunction();
}
Я могу изменить f на
void f(QList<const T *> list)
Но тогда я не могу сделать
f(QList<T *>()); //Compile error
Больше, так как компилятор не может имплицитно привести QList<T *> к QList<const T *>. Однако я могу явно переинтерпретировать QList следующим образом:
template <typename T> inline QList<const T *> &constList(const QList<T *> &list)
{
return (QList<const T *> &)list;
}
Это позволяет мне использовать функцию шаблона constList для приведения любого QList<T *> в QList<const T *>, как в
f(constList(QList<T *>()));
И это, кажется, работает нормально, но на самом деле безопасно ли это делать вот это?
2 ответа:
Функция приведения, которую вы рассматриваете, ...
template< class T > inline QList<T const*>& constList( QList<T*> const& list ) { return reinterpret_cast< QList<T const*>& >( const_cast< QList<T*>& >( list ) ); }... может быть практичным (вероятно,
QListне изменяет своего объектного представления в зависимости отconst-ности типа элемента), но он может нарушатьconstкорректность.Во-первых, потому что отбрасывание
const- ности самого списка не являетсяconstправильным: это позволяет изменить исходный списокconst.Но даже если этот формальный Аргумент
constбудет удален, как ...template< class T > inline QList<T const*>& constList( QList<T*>& list ) { return reinterpret_cast< QList<T const*>& >( list ); }... есть все еще проблема корректности
Причина в том, что список представляет собой дополнительный уровень косвенности, а с вашей функцией не является самим собойconst.const. Таким образом, после использования функции для получения ссылки на список с предполагаемым указателем на элементыconst, Вы можете сохранить в этом списке указатель на то, что на самом деле являетсяconst. И тогда вы можете использовать исходный список, чтобыизменить , что действительноconstэлемент, bang .Это та же самая причина, по которой существует нет неявного преобразования из
Что вы можете сделать без таких проблем, так это, имея ужеT**вT const**.constсписок указателей на объекты, сделать так, чтобы они указывали на объектыconst:Формальноtemplate< class T > inline QList<T const*> const& constList( QList<T*> const& list ) { return reinterpret_cast< QList<T const*> const& >( list ); }Все еще существует
reinterpret_castкак потенциальная проблема, но любой, кто специализируется на представленииQListо постоянстве элементов, вероятно, заслуживает того, что они получили. :- )Ура и ХТ.,
Идея корректности Const слаба, и то, что вы обнаружили, является одной из многих причин. Концепция Constness захватывает только один бит семантики (change / don't change) и делает это настолько плохо и с довольно высокой стоимостью синтаксиса, что иногда даже требует дублирования кода.
Одна из проблем этой концепции заключается в том, что она плохо масштабируется по составу: например, мне было бы интересно передать функции вектор const неконстантных объектов, или вектор const неконстантных объектов, или вектор const const объектов и получение правильного синтаксиса является дорогостоящим... просто рассмотрим, как стандартный c++ был вынужден ввести
За эти годы я перешел от фанатичной позиции использования const корректности во всех возможных местах к противоположной позиции использования ее только там, где я вынужден. Опыт научил меня, что код, который не одержим корректностью const, становится чище, и что механизм корректности const никогда по-настоящему не ловит (по крайней мере, для me) любая логическая ошибка, но только ошибки о самой машине корректности const. К сожалению, корректность const-это одна из вещей в C++, которую вы вынуждены использовать, потому что правила C++ так говорят, и нет никакого способа просто избежать ее использования.const_iterator, потому что это, конечно, отличается отconst iterator.Я знаю, что меня понизят в должности, но мое предложение состоит в том, чтобы критически следить за всем, что Вы читаете о C++ на эту тему; держите мозг включенным и судите объективно. Просто потому, что было бы хорошо, если бы что-то было правдой (например, что const корректность помогает программисту) к сожалению, это не значит, что это действительно так.
Неважно, насколько велико имя, подписавшее книгу.Также помните, что если позиция требует, чтобы весь остальной мир был неправ, то, вероятно, неплохо быть хотя бы немного скептиком: большинство языков, даже те, которые родились после C++, не реализуют эту концепцию.