Продайте меня на const const

Итак, почему именно он всегда рекомендовал использовать const как можно чаще? Мне кажется, что использование const может быть больнее, чем помощь на С++. Но опять же, я прихожу к этому с точки зрения python: если вы не хотите, чтобы что-то изменилось, не меняйте его. Итак, с учетом сказанного, вот несколько вопросов:

  • Кажется, каждый раз, когда я отмечаю что-то как const, я получаю сообщение об ошибке и должен изменить какую-то другую функцию, чтобы быть const. Тогда это заставляет меня менять другую функцию в другом месте. Это что-то, что просто становится легче с опытом?

  • Являются ли преимущества использования const действительно достаточными для компенсации проблемы? Если вы не собираетесь менять объект, почему бы просто не написать код, который его не изменит?

Я должен отметить, что на данный момент я больше всего сфокусирован на преимуществах использования const для корректности и удобства обслуживания, хотя также приятно иметь представление о последствиях производительности.

Ответ 1

Это окончательная статья о "const correctness": https://isocpp.org/wiki/faq/const-correctness.

В двух словах использование const - хорошая практика, потому что...

  • Он защищает вас от случайного изменения переменных, которые не предназначены для изменения,
  • Он защищает вас от случайных присвоений переменных и
  • Компилятор может оптимизировать его. Например, вы защищены от

    if( x = y ) // whoops, meant if( x == y )
    

В то же время компилятор может генерировать более эффективный код, поскольку он точно знает, какое состояние переменной/функции будет всегда. Если вы пишете жесткий код на С++, это хорошо.

Вы правы в том, что может быть сложно использовать константу-правильность последовательно, но конечный код более краткий и безопасный для программирования. Когда вы делаете много развития на С++, преимущества этого быстро проявляются.

Ответ 2

Здесь фрагмент кода с общей ошибкой, которая корректна для const, может защитить вас от:

void foo(const int DEFCON)
{
   if (DEFCON = 1)     //< FLAGGED AS COMPILER ERROR! WORLD SAVED!
   {
       fire_missiles();
   }
}

Ответ 3

Кажется, каждый раз, когда я отмечаю что-то как const, я получаю сообщение об ошибке и должны изменить другую функцию где-то тоже будет const. Тогда это заставляет меня изменить другую функции в другом месте. Это то, что становится проще с опыт?

Из опыта это полный миф. Это происходит, когда не const-правильно сидит с константным кодом, конечно. Если вы проектируете const-correct с самого начала, это НИКОГДА не должно быть проблемой. Если вы создаете что-то const, а затем что-то еще не усложняет, компилятор сообщает вам что-то чрезвычайно важное, и вы должны потратить время, чтобы исправить его правильно.

Ответ 4

Это не для вас, когда вы сначала пишете код. Это для кого-то другого (или вас через несколько месяцев), который смотрит на объявление метода внутри класса или интерфейса, чтобы увидеть, что он делает. Не изменять объект - это значительная часть информации, которую можно извлечь из этого.

Ответ 5

const - это обещание, которое вы делаете как разработчик, и привлечение помощи компилятора в обеспечении соблюдения.

Мои причины для const-correct:

  • Он связывается с клиентами вашей функции, что вы не будете изменять переменную или объект
  • Принятие аргументов с помощью ссылки const дает вам эффективность передачи по ссылке с безопасностью передачи по значению.
  • Написание ваших интерфейсов как const корректно позволит клиентам использовать их. Если вы напишете свой интерфейс для использования в неконстантных ссылках, клиенты, которые используют константу, должны будут указывать константу, чтобы работать с вами. Это особенно раздражает, если ваш интерфейс принимает non-const char *, а ваши клиенты используют std:: strings, так как вы можете получить от них только const char *.
  • Использование const потребует компилятора, чтобы вы были честны, поэтому не ошибетесь, измените то, что не должно меняться.

Ответ 6

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

Ответ 7

Программирование С++ без const похоже на вождение без ремня безопасности.

Это боль, чтобы поместить ремень безопасности каждый раз, когда вы входите в машину, и 364 из 365 дней вы прибудете безопасно.

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

Ответ 8

Моя философия заключается в том, что если вы собираетесь использовать nit-picky язык с проверкой времени компиляции, чем использовать его наилучшим образом, вы можете. const - это принудительный способ компиляции для передачи того, что вы означают... это лучше, чем комментарии или doxygen когда-либо. Вы платите цену, почему бы не получить стоимость?

Ответ 9

Для встроенного программирования, используя const разумно, когда объявления глобальных структур данных могут сэкономить много ОЗУ, заставляя постоянные данные располагаться в ПЗУ или мигать без копирования в ОЗУ во время загрузки.

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

При работе с другими программистами в крупных проектах использование const правильно помогает предотвратить дросселирование других программистов.

Ответ 10

const помогает вам изолировать код, который "меняет вещи" за вашей спиной. Итак, в классе вы отметите все методы, которые не изменят состояние объекта как const. Это означает, что экземпляры const этого класса больше не смогут вызывать какие-либо методы не const. Таким образом, вы не можете случайно вызвать функциональность, которая может изменить ваш объект.

Кроме того, const является частью механизма перегрузки, поэтому вы можете иметь два метода с одинаковыми сигнатурами, но один с const и один без него. Тот, у кого const, вызывается для ссылок const, а другой - для ссылок <<20 > .

Пример:

#include <iostream>

class HelloWorld {
    bool hw_called;

public:
    HelloWorld() : hw_called(false) {}

    void hw() const {
        std::cout << "Hello, world! (const)\n";
        // hw_called = true;  <-- not allowed
    }

    void hw() {
        std::cout << "Hello, world! (non-const)\n";
        hw_called = true;
    }
};

int
main()
{
    HelloWorld hw;
    HelloWorld* phw1(&hw);
    HelloWorld const* phw2(&hw);

    hw.hw();    // calls non-const version
    phw1->hw(); // calls non-const version
    phw2->hw(); // calls const version
    return 0;
}

Ответ 11

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

В большом количестве кода, который я пишу, его действительно стоило усилий, потому что мы склонны много использовать композицию:

class A { ... }
class B { A m_a; const A& getA() const { return m_a; } };

Если бы у нас не было const-correctness, вам пришлось бы прибегать к возврату сложных объектов по стоимости, чтобы убедиться, что никто не манипулировал внутренним состоянием класса B. За вашей спиной.

Короче говоря, const-correctness - это защитный механизм программирования для спасения от боли по дороге.

Ответ 12

Скажем, у вас есть переменная в Python. Вы знаете, что вы не должны изменять его. Что делать, если вы случайно делаете?

С++ дает вам возможность защитить себя от случайного выполнения того, что вы не должны были делать в первую очередь. Технически вы можете обойти это в любом случае, но вам нужно добавить дополнительную работу, чтобы стрелять в себя.

Ответ 13

Есть хорошая статья здесь о const в С++. Это довольно прямое мнение, но надеюсь, что это поможет некоторым.

Ответ 14

Когда вы используете ключевое слово "const", вы указываете другой интерфейс для своих классов. Существует интерфейс, который включает в себя все методы и интерфейс, который включает только методы const. Очевидно, это позволяет ограничить доступ к некоторым вещам, которые вы не хотите изменять.

Да, со временем становится легче.

Ответ 15

Мне нравится константная корректность... в теории. Каждый раз, когда я пытался применить его на практике, он в конечном итоге сломался, и const_cast начинает ползать, делая код уродливым.

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

Например, представьте простой механизм базы данных... у него есть объекты схемы, таблицы, поля и т.д. У пользователя может быть указатель "const Table", означающий, что им не разрешено изменять схему таблицы непосредственно... но как насчет манипуляции данными, связанными с таблицей? Если метод Insert() отмечен как const, то он должен отбросить константу, чтобы фактически манипулировать базой данных. Если он не помечен как const, он не защищает от вызова метода AddField.

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

Ответ 16

Вы также можете дать подсказки компилятора с константой... согласно следующему коду

#include <string>

void f(const std::string& s)
{

}
void x( std::string& x)
{
}
void main()
{
    f("blah");
    x("blah");   // won't compile...
}

Ответ 17

Также без const-коррекции вы не можете передавать аргументы с помощью ссылки const, что может привести к большему количеству копий. Передача по (не const) ссылке не является решением, поскольку ссылки non const не могут быть привязаны к временным.