Что не так с const? - PullRequest
       1

Что не так с const?

12 голосов
/ 12 января 2011

Каковы известные недостатки const в C ++ и C ++ 0x?

Ответы [ 12 ]

55 голосов
/ 12 января 2011

Единственное, что не так с const, это то, что серьезно недооценено многими разработчиками . Это один из лучших инструментов в C ++, очень острый, но не опасный для себя.

49 голосов
/ 12 января 2011

Основная проблема в том, что вы должны написать это. Это должно быть значение по умолчанию, и все изменяемые переменные или параметры должны быть указаны явно.

17 голосов
/ 12 января 2011

Что не так с const, так это то, что многие программисты, кажется, не в состоянии понять его полностью, и «полуконстантный» проект просто не работает. Это то, что вам нужно знать:

  1. Foo против const Foo (или Foo const)
  2. Foo& против const Foo& (или Foo const&)
    • ссылки на const привязываются ко всем видам вещей, тогда как ссылки на non-const не
  3. Foo* против const Foo* (или Foo const*)
    • переменные указателя также могут быть Foo* const и const Foo* const (или Foo const* const)
  4. void Foo::mutator() против int Foo::accessor() const
    • но члены-указатели внутри константных функций-членов по-прежнему указывают на неконстантные объекты
    • чтобы мы могли случайно вернуть неконстантные данные из const-функции
  5. iterator против const_iterator
    • переменные итератора также могут быть const iterator и const const_iterator

Миграция на C ++ с языка, который не имеет концепции const, довольно сложна, многие не видят смысла.

16 голосов
/ 12 января 2011

Двумя основными проблемами, на которые я часто сталкивался с жалобами в группах новостей, являются

Я думаю, что последний мог / должен быть поддержан языком.

Возможно, в сочетании с поддержкой реализаций ковариантных функций-членов, потому что оба нуждаются в некотором способе подобрать тип указателя this.

Третья проблема заключается в том, что

Приветствия & hth.,

3 голосов
/ 12 января 2011

Одна вещь, которая является «неправильной», заключается в том, что вы не можете преобразовать T ** в T const * const *, что должно быть разрешено, поскольку это не опасно. Недопустимо преобразование T ** в T const **, это преобразование недопустимо.

Я иногда упоминал, что const на самом деле является дешевым способом "разбить" ваш интерфейс на методы только для чтения и методы записи. Это было бы непрактично в C ++. В Java было бы более практично иметь версии коллекций ReadOnly, где они не имеют const и где их типы коллекций более объектно-ориентированы.

const-ness не распространяется: проблема здесь в том, что если я pImpl мой класс, constness не "проверяется" компилятором, то есть мой класс интерфейса может иметь метод "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 *), которым они не являются.

3 голосов
/ 12 января 2011

Проблема с const заключается в том, что программисты неправильно его используют.

1 голос
/ 12 января 2011

"вопросы"?

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

Современные версии gcc поддерживают предупреждение при попытке преобразовать переменную const в переменную не const. Я предлагаю вам оставить эти предупреждения включенными.

Единственное, на что нужно обратить внимание, это точно что вы отмечаете const; const char * foo() не совпадает с char * foo() const.

0 голосов
/ 01 октября 2012

const отлично.const важно.const -корректность является необходимым условием для хорошего API.

Тем не менее есть две проблемы, с которыми я неоднократно сталкивался с const.

  • Естьнет способа пометить переменную как const задним числом.Вы должны либо объявить код переменной, в этом случае у вас есть , чтобы немедленно инициализировать его.Что если код инициализации содержит if?Вы можете либо опустить const (нежелательно), используя оператор ? вместо if (вредит читабельности).С Java все в порядке, BTW - const переменные не нужно инициализировать сразу, они просто должны быть инициализированы до их первое чтение, и они должны быть инициализированы в все ветви if.

  • Нет способа указать, что объект, переданный по ссылке на функцию, не изменится в течение всего времени вызова функции.const T& t означает , а не означает, что объект, на который указывает t, не изменится, а только то, что ссылка t не может быть использована для его изменения.Компилятор все еще должен предполагать, что любой вызов функции, который он не видит в , может изменить объект.В некоторых случаях это предотвращает немало оптимизаций.

0 голосов
/ 28 ноября 2011

В большинстве ответов ниже говорится о том, что «что не так с const, так это то, что X люди делают Y». Это не ответы, а симптомы . Это не плохо с const. едва что-то не так с const ... С людьми, которые не могут RTFM , это не так

0 голосов
/ 01 июля 2011

Еще одна проблема, которая еще не была упомянута, - это возможность плохо спроектированного интерфейса подменить 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 означает, что возможно иметь интерфейс, где неконстантная ссылка на объект может быть получена из константной ссылки на объект.Об этом следует помнить при разработке интерфейсов.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...