Каковы известные недостатки const
в С++ и С++ 0x?
Что не так с const?
Ответ 1
Два основных вопроса, которые я часто встречал в новостных группах, - это
-
Необходимо тратить много времени на поддержку API, не поддерживающих независимость (особенно Microsoft).
-
необходимо определить как константную, так и неконвертную версию метода.
Я думаю, что последний может/должен поддерживаться языком.
Возможно, в сочетании с поддержкой ковариантных реализаций функций-членов, поскольку для этого нужен способ получения типа указателя this
.
Третий вопрос:
Приветствия и hth.,
Ответ 2
Единственное, что не так с const
, это то, что он серьезно недооценен для многих разработчиков. Это один из лучших инструментов в С++ toolbox, очень четкий, но не опасный для себя.
Ответ 3
Основная проблема заключается в том, что вы должны ее написать. Он должен быть по умолчанию, и все изменяемые переменные или параметры должны быть указаны явно.
Ответ 4
Что не так с const
заключается в том, что многие программисты, похоже, не в состоянии полностью его понять, а проект с половинной константой просто не работает. Это то, что вам нужно знать:
-
Foo
vs.const Foo
(илиFoo const
) -
Foo&
vs.const Foo&
(илиFoo const&
)- reference-to-const привязывается ко всем видам вещей, а ссылки-не-const не
-
Foo*
vs.const Foo*
(илиFoo const*
)- переменные-указатели также могут быть
Foo* const
иconst Foo* const
(илиFoo const* const
)
- переменные-указатели также могут быть
-
void Foo::mutator()
противint Foo::accessor() const
- но элементы-указатели внутри функций-членов-констант по-прежнему указывают на не-const-объекты
- поэтому мы можем случайно вернуть неконстантные данные из const-функции
-
iterator
vs.const_iterator
- переменными итератора также могут быть
const iterator
иconst const_iterator
- переменными итератора также могут быть
Переход на С++ с языка, который не имеет концепции const, довольно сложно, многие из них не видят точку.
Ответ 5
Проблема с const - это программисты, которые неправильно используют это непоследовательно
Ответ 6
Одна вещь, которая является "неправильной", заключается в том, что вы не можете преобразовать T ** в T const * const *, который должен быть разрешен, потому что это не опасно. Невозможно преобразовать T ** в T const **, это преобразование недействительно.
Я иногда упоминал, что const фактически является дешевым способом "разделить" ваш интерфейс на методы только для чтения и методы записи. Вероятно, это было бы нецелесообразно в С++. В Java было бы более практично иметь версии коллекций ReadOnly, хотя они не имеют const и где их типы коллекций более объектно ориентированы.
const-ness не распространяется: проблема заключается в том, что если я pImpl мой класс, константа не "проверяется" компилятором, то есть мой класс интерфейса может иметь метод "const", вызывающий неконстантный метод на pImpl и компилятор не будут жаловаться. Это потому, что единственное, что мой const-метод не гарантирует, - это изменить указатель на другой объект, и мой pImpl никогда не изменится. Это может быть даже указатель const (не указатель на const).
Отсутствие надлежащей ковариации между shared_ptr<T>
и shared_ptr<const T>
также может быть проблемой, хотя, как правило, я видел, что это не проблема, но разработчики обычно типизируют свои shared_ptrs и редко набирают значение shared_ptr для Уст. И они иногда передают const shared_ptr<T> &
и думают, что они передают общий указатель на const T (как и для const T *), которым они не являются.
Ответ 7
"проблемы"?
Если вы не собираетесь изменять значение пройденного указателя (оно используется исключительно для ввода-вывода по ссылке для функции), отметьте его const
. То же самое, если значение определенной переменной не изменится после ее инициализации. Если функция безопасна для вызова экземпляра класса const
, отметьте его const
тоже. Чем больше элементов правильно аннотируется const
, тем меньше вероятность того, что вы случайно сделаете ошибку, и тем больше оптимизаций, которые компилятор теоретически сможет выполнить в отсутствие полных знаний (например, при компиляции с использованием только прототипов функций).
В современных версиях gcc есть поддержка предупреждений при попытке применить переменную const
к const
. Я предлагаю вам оставить эти предупреждения включенными.
Единственное, на что нужно обратить внимание, это именно то, что вы отмечаете const
; const char * foo()
не совпадает с char * foo() const
.
Ответ 8
Еще одна проблема, о которой еще не упоминалось, - это возможность плохо спроектированного интерфейса для отклонения const (даже при отсутствии отбрасываний).
Пример:
class TreeNode {
public:
TreeNode& getParent() const { return *parent_; }
TreeNode& getLeft() const { return *left_; }
TreeNode& getRight() const { return *right_; }
private:
//TreeNode has a pointer to the Tree to enable navigation of the tree.
//Assume that other design constraints mean that this must be a pointer
//rather than a reference.
TreeNode* parent_;
TreeNode* left_;
TreeNode* right_;
};
//This function demonstrates the ability for const to be subverted.
TreeNode& remove_const(TreeNode const& toRemoveConstFrom) {
TreeNode& parent(toRemoveConstFrom.getParent());
TreeNode& leftChild(parent.getLeft());
TreeNode& rightChild(parent.getRight());
return &toRemoveConstFrom == &leftChild ? leftChild : rightChild;
}
Непереходный характер const означает, что возможно иметь интерфейс, где неконстантная ссылка на объект может быть получена из ссылки const на объект. Это необходимо соблюдать при разработке интерфейсов.
Ответ 9
Большинство ответов ниже состояний, таких как "что не так с const
, это то, что X люди делают Y". Это не ответы, а симптомы. В const
это не так. Там едва ли что-то не так с const
... Это неправильно с людьми, которые не могут RTFM.
Ответ 10
const
отлично. const
важен. const
-корректность - это необходимое условие для хорошего API.
Тем не менее, есть две проблемы, которые у меня были с const
, несколько раз.
-
Невозможно пометить переменную как
const
ретроактивно. Вы должны либо объявить переменный код, и в этом случае вы должны его инициализировать немедленно. Что делать, если код инициализации содержитif
, хотя? У вас есть выбор либо опускатьconst
(нежелательно), используя оператор?
вместоif
(вредит читаемости). Java это правильно, переменные BTW -const
не обязательно должны быть инициализированы сразу, их нужно просто инициализировать до их первого чтения, и их нужно инициализировать во всех ветвяхif
. -
Невозможно указать, что объект, переданный по ссылке на функцию, не будет меняться в течение продолжительности вызова функции.
const T& t
не означает, что объект, на который указываетt
, не изменится, но только то, что ссылкаt
не может быть использована для его изменения. Компилятор все же должен предположить, что любой вызов функции, который он не видит, может изменить объект. В некоторых случаях это предотвращает довольно много оптимизаций.
Ответ 11
Одна из проблем заключается в том, что язык также позволяет вам const_cast его, что в первую очередь поражает цель использования const.
Ответ 12
Одно дело, что все еще возможно подорвать его. то есть законно делать что-то вроде этого:
void foo(const inst& x)
{
const_cast<int&> x = 3;
}
Вы можете даже использовать такие вещи, как memset
, чтобы подорвать его без явного const_cast
.
Это компромисс между наличием компилятора const
и возможностью некоторой гибкости для интерфейсов с поддержкой не const
.
Это приводит к другому ограничению, поскольку оно не было общепринятым, что частично связано с другой проблемой, которая заключается в том, что использование const
является предложением "все или ничего". Если вы начнете использовать его, вам нужно будет распространять его на всей базе кода.