тогда как в неконстантно-корректных языках вы можете случайно изменить что-то задокументированное как инвариантное.

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

 Puppy12 янв. 2011 г., 17:59
Интересно посмотреть, сколько раз этот вопрос закрывается и вновь открывается.
 Ring Ø12 янв. 2011 г., 15:37
Единственная проблема, которую я вижу сconst это его готовность иundertandiness варьируется в широких пределах в зависимости от уровня программиста C ++ (некоторая путаница в отношении того, какой элементconst применяется в сложной декларации, например). Кроме того, это часть языка, и ее следует использовать - до тех пор, пока книга Б.Струструпа прочитана :-)
 BlackBear12 янв. 2011 г., 15:28
Я думаю, что они полезны, потому что облегчают понимание кода.
 David Heffernan12 янв. 2011 г., 15:31
Нужно сформулировать вопрос, прежде чем вы получите ответ, Minks
 BlackBear12 янв. 2011 г., 15:38
@ Vilx, ты не думаешь, что "while (x <ThingsToDo)" имеет гораздо больше смысла, чем "while (x <314145.315)" ??

Ответы на вопрос(12)

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

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

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

 Lightness Races in Orbit13 янв. 2011 г., 11:45
Многие программисты не понимают, что это не проблемаconst, Это проблема с программистами и серьезным патетическим состоянием обучения программированию в западном мире.
 fredoverflow12 янв. 2011 г., 16:02
@Phil: Хорошо, я изменил соответствующие части с английского на C ++ ;-)
 fredoverflow15 февр. 2013 г., 13:25
@ OververEdge Я предлагаю вам купить «Эффективный C ++» (3-е издание) Скотта Мейерса. Пункт 3 посвящает 10 страниц этой теме.
 Philipp12 янв. 2011 г., 15:50
Проницательность: ссылки на объекты не могут быть константными, но ссылки могут ссылаться на константные объекты. (Большинство людей знают, что вы имеете в виду, но различие более важно для указателей, где у нас есть как const-указатели, так и указатели на const.)
 Chris Lutz13 янв. 2011 г., 11:48
void int Foo::accessor() ?

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

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

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

 Puppy12 янв. 2011 г., 17:59
Я не спрашиваю, как использовать const. Я уже знаю, как использовать const. Я искалпроблемы с конст.

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

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

Нет способа пометить переменную какconst задним числом. Вы должны либо объявить код переменной, в этом случае выимеют немедленно инициализировать его. Что делать, если код инициализации содержитif, хотя? У вас есть выбор: пропуститьconst (нежелательно), используя оператор? вместоif (ухудшает читабельность). Я понял, правильно, кстати -const переменные не должны быть инициализированы сразу, они просто должны быть инициализированыдо они сначала читаются, и они должны быть инициализированы ввсе ветвиif.

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

Решение Вопроса

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

Необходимость тратить много времени на поддержку неконстантных API (особенно Microsoft).

необходимо определить как постоянную, так и неконстантную версию метода.

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

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

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

const не распространяется на принадлежащие объекты.

Ура & hth.,

 Motti13 янв. 2011 г., 08:17
Возможно, это не чисто Win32, а COMBSTR не может бытьconst (так как этоtypedef что не позволяет положитьconst на правильной части типа).
 Puppy12 янв. 2011 г., 16:16
@Rup: Многие API-интерфейсы Microsoft не используют много констант. Когда в последний раз вы видели const HANDLE? Или const IDirect3DDevice9 *? Microsoft использует const для строк, и это все.
 Johannes Schaub - litb13 янв. 2011 г., 11:57
+1 за «Необходимость определения как постоянной, так и неконстантной версии метода». !
 Rup12 янв. 2011 г., 15:37
Какие API-интерфейсы Microsoft не учитывают констант? IIRC Windows API использует LPCTSTR, MFC использует const правильно IIRC и т. Д. Я не могу думать ни о каком.
 Philipp12 янв. 2011 г., 18:30
@DeadMG: AHANDLE это непрозрачный объект, который вы не можете изменить в любом случае без использования функций API. Для интерфейсов COM они используют такие атрибуты, как[in] а также[out], И для большинства других типов C они используютconst.

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

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

 Konrad Rudolph12 янв. 2011 г., 15:55
Не могу высказать это достаточно. Даже если (или потому что) это нанесло бы ущерб предвзятому мнению большинства программистов.
 Lightness Races in Orbit13 янв. 2011 г., 11:44
Вы никогда не найдете, что так или иначе лучше. Некоторые объекты, которые вы создаете для чтения / записи (счетчики циклов, итераторы, контейнеры, потоки, большинство строк) и другие, которые вы назначаете только один раз - на самом деле, я не могу придумать ни одного примера для этого. Почему ваши одноразовые записи не постоянные инициализации?
 Konrad Rudolph12 янв. 2011 г., 23:33
@Jay «Большинство переменных созданы для записи.» -однажды, Редко я изменяю значение переменной после ее первого присваивания (контейнеры являются своего рода исключением).
 Jay12 янв. 2011 г., 19:28
За исключением двух вещей: большинство переменных создаются для записи. Наличие их по умолчанию только для чтения создает дополнительную работу. Кроме того, философия языка C и C ++ заключается в том, что программист знает, что он делает, и язык не должен мешать вам делать то, что вы когда-либо хотите.
 fredoverflow12 янв. 2011 г., 18:38
Ура для F # переменных :)

что программисты, которые используют его неправильно, непоследовательно

что язык также позволяет вам использовать const_cast, что в первую очередь лишает смысла использование const.

 Steve Jessop12 янв. 2011 г., 15:53
@FredOverflow: но, может быть, было бы хорошо, если бы за этими программистами охотились и убивали люди, которые больше не могут обходить свой неработающий код с помощью константного преобразования? ;-) Что касается древнего кода - что-то может все еще быть недостатком языка, даже если мотивация для этого недостатка состоит в поддержке предварительно стандартного кода и / или соглашений. Например, вы можете подумать, что автоматическое преобразование вvoid* недостаток C ++: он необходим, например, дляstd::memcpy, но в контексте C ++ функции не должны быть спроектированы так, чтобы молча принимать любой указатель независимо от безопасности типов.
 fredoverflow12 янв. 2011 г., 15:56
@ Dave:Почему разработчик выбросил это? Большинство бросков являются злыми и / или ненужными. Если вы не доверяете программистам, C ++ - неправильный язык.
 fredoverflow12 янв. 2011 г., 17:15
@ Стив: Как бы их убитьв настоящее время решать проблему? Пусть проклятые терминаторы сделают всю работу тщательно и сотрут неверующих из истории!
 Lightness Races in Orbit13 янв. 2011 г., 11:48
Нет хотяconst_cast законно, запись в объект, созданный какconst (даже если вы отбросили константу напеременная) не является законным.
 fredoverflow12 янв. 2011 г., 15:38
Не это снова ...const было бы бесполезнобез возможность отбросить его, потому что в реальном коде вам приходится иметь дело с API, написанными программистами, которые не понимают правильности констант (или когда-то давноconst еще не был частью C ++).

что все еще возможно подорвать это. то есть все еще законно делать что-то вроде этого:

void foo(const inst& x)
{
   const_cast<int&> x = 3;
}

Вы даже можете использовать такие вещи, какmemset подорвать его без явногоconst_cast.

Это компромисс между применением компиляторомconst и предоставляя некоторую гибкость для неconst осведомленные интерфейсы.

Что приводит к другому ограничению, заключающемуся в том, что оно не было принято повсеместно, что отчасти связано с другой проблемой, которая заключается в использованииconst это предложение "все или ничего". Если вы начнете использовать его, вам нужно будет распространять его по всей базе кода.

 Sebastian Mach25 авг. 2011 г., 09:13
Но вы можете давать обещания в виде комментариев на каждом языке, а затем подрывать их.const однако это некомментированный / встроенный инструмент, который заставляет вас не нарушать договорпо умолчаниютогда как в неконстантно-корректных языках вы можете случайно изменить что-то задокументированное как инвариантное.
 JohnMcG13 янв. 2011 г., 16:22
Ну, да, но если вы считаете, что с точки зрения контракта или обещания, что я не изменяю (даже если раньше он был неконстантным), то его можно нарушить.
 Lightness Races in Orbit13 янв. 2011 г., 11:47
Нет, это возможно неопределенное поведение (если исходный объект был созданconst) и в контексте этой функции должны быть приняты.const_cast законно, но запись в объект, созданный какconstНезависимо от того, изгнали ли вы постоянство или нет, это незаконно.

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

 Fred Nurk18 янв. 2011 г., 07:44
«Но те, кто смеялся надо мной, перестали смеяться, когда через несколько дней стало очевидным, что некоторые из них, которые очень трудно воспроизвести, исчезли, и некоторые из моих коллег отчаянно искали». (изчат)

const является то, что X люди делают Y ". Это не ответы, носимптомы, Это не так плохо сconst, Там ведва что-то не так сconst...Это плохо с людьми, которые не могут RTFM.

которая является «неправильной», заключается в том, что вы не можете преобразовать 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> тоже может быть проблемой, хотя в целом я видел, что проблема не в этом, но в том, что разработчики обычно вводят typedef для своих shared_ptrs и редко вводят определение shared_ptr для const. И они иногда будут проходитьconst shared_ptr<T> & и подумайте, что они передают общий указатель на const T (как с const T *), которым они не являются.

 smerlin13 янв. 2011 г., 12:04
у вас может быть const-проверка для класса pimpl, ничего страшного ... например, посмотрите на использование Qts классов pimpl .. (они используют 2 приватные функции доступа к pimpl (const / nonconst) для доступа к объекту pimpl, если вы хотите чтобы убедиться, что у вас нет доступа к объекту pimpl без использования этих функций (и, следовательно, обхода проверки const), вы можете использовать полностью непрозрачныйvoid* для объекта pimpl и добавьте некоторые reinterpret_casts к функциям-адсорам (посмотрите на реализацию, то есть Q_DECLARE_PRIVATE)
 CB Bailey13 янв. 2011 г., 12:49
@anatolyg: Вы правы. Первый абзац не описывает что-то «не так» сconst потому что это не правда. См. 4.4 [conv.qual] / 4 ISO / IEC 14882: 2003.
 anatolyg12 янв. 2011 г., 18:31
"не может конвертироватьT** вT const * const *"- эта часть неверна (по крайней мере, с компиляторами, которые я использую); я помню, что это было раздражение в C, но C ++ понял это правильно.

Ваш ответ на вопрос