В C / C ++ я должен использовать 'const' в параметрах и локальных переменных, когда это возможно?


13

Этот вопрос вдохновлен вопросом о finalв Java .

В C / C ++ я должен использовать, constкогда это возможно?

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

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

Итак, я должен использовать, constкогда это возможно? Если так, то почему совет constв C ++ отличается от совета finalв Java?

Ответы:


18

Прежде всего, поскольку вы ссылались на Java final, это совершенно другой зверь, чем const. Окончательный означает, что ссылка не может измениться, но ничего не говорит об изменчивости. Const идет дальше, говоря: «ссылка на const не может изменяться», что является гораздо более сильной гарантией. Чтобы сделать это в Java, внутреннее состояние должно быть окончательным и определяться во время построения. Const намного проще в использовании, и существующий объект можно «продвинуть» в ссылку на const.

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

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


1
Голосуйте, потому что вы объясняете это finalи constне имеете таких же гарантий.
Билл Дверь

2
Constness - это возможность записи, а не изменчивость.
Basilevs

@Basilevs, что произойдет, если вы напишите объект? Это мутирует. Как вы мутируете объект? Напиши ему.

4
Что произойдет, если вы напишете ссылку на const? Ошибка времени компиляции. Что произойдет, если вы запишете объект, на который ссылается где-то по константной ссылке через другую неконстантную ссылку? Это мутирует. Неизменяемый объект не может изменяться, поэтому ссылка на const не обязательно ссылается на неизменяемый объект.
Basilevs

@Basilevs ваше наблюдение относится только к постоянным ссылкам. Если сам объект объявлен как const (а не просто ссылка), он становится более или менее неизменным (если только кто-то не отбросил константность).
Мэтью Джеймс Бриггс

4

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

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


4

Я собираюсь не согласиться с другими авторами и рекомендую не использовать верхний уровень constдля локальных переменных и параметров. (Ссылки и указатели на const, т. const T&Е. Разные, и вы должны использовать их для правильности всегда, когда это уместно.)

Преимуществами верхнего уровня constявляются:

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

Недостатки:

  • Визуальный беспорядок.
  • Не может использоваться с переменными «псевдо-const», т. Е. Переменными, которые инициализируются некоторым образом более сложным, чем прямое построение, но не модифицируются после, например, с использованием getline:

    std::string line; // cannot be const
    std::getline(std::cin, line);
    // line should be const from here on out
  • Предотвращает оптимизацию перемещения при вызове функции и возврате:

    std::string f1();
    std::string f2(std::string s);
    std::string f3() {
      const std::string s = f1(); // s is not meant to be modified
      // but I still want the move optimization here:
      const std::string result = f2(std::move(s)); // this doesn't move
      // and I want the compiler to move out here:
      return result; // this will probably RVO, but if not, the move
                     // constructor will not be used due to the const
    }

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


2
Ваша точка зрения о переносе с показа показывает, где вы не используете локальный язык в постоянной форме, поскольку вы (намереваетесь) изменить его с ходом
Caleth

1
@Caleth Нет, в этом все дело. Я не собираюсь изменять это. Я просто хочу передать значение или вернуть его, и я хочу, чтобы оно было эффективным. Концептуально модификация - это просто оптимизация, которая не предназначена для наблюдения (поскольку переменные впоследствии не используются). Практически, да, есть модификация, так как C ++ не имеет истинных разрушительных движений (как у Rust). Именно поэтому я не хочу, чтобы constместные жители: потому что это предотвращает технические изменения, а не только концептуальные изменения.
Себастьян Редл

2
Вы не хотите изменять значение , но вы хотите изменить переменную . Вместо этого вы можете вместо этого использовать const & и не изменять ни одного
Caleth 25.10.16

2

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

  • Проще прочитать код. Когда кто-то читает объявление переменной, он знает, что оно не изменится. Еще одна вещь, о которой стоит беспокоиться при чтении вашего кода.
  • Предотвратить случайное изменение переменной
  • Нет штрафа за время выполнения, все проверено статически. Это как бесплатный обед, constнаписание которого занимает всего секунду, так что это не страшно.
  • Всегда полезно создавать переменные / параметры в многопоточных приложениях. Даже ваше приложение не является многопоточным, это все еще хорошая привычка.
  • Вы даете возможность вашему компилятору C ++ оптимизировать ваш код.

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

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.