Чи потрібно в C / C ++ використовувати "const" у параметрах та локальних змінних, коли це можливо?


14

Це питання надихає запитання про finaljava .

Чи потрібно використовувати C / C ++, constколи це можливо?

Я знаю, що вже є пов'язане питання щодо використання constв параметрах . На жаль, це питання та його відповіді не відповідають повністю на моє запитання, оскільки мова йде лише про параметри функції, але я також хотів би знати про інші випадки (наприклад, локальні змінні).

Крім того, майже всі відповіді на це питання кажуть, що ми повинні використовуватись, constоскільки вона містить корисну інформацію про доступність змінних. Але це, здається, суперечить відповіді про використання Final у Java, яка finalможе бути зайвою, якщо вона не містить додаткової інформації, і тому її потрібно пропустити, щоб код був коротким та чистим.

Отже, я повинен використовувати, constколи це можливо? Якщо так, то чому поради для constC ++ відрізняються від порад для finalJava?

Відповіді:


19

Перш за все, оскільки ви посилалися на Java final, це зовсім інший звір, ніж const. Останнє означає, що посилання не може змінитися, але нічого не говорить про можливість зміни. Конст іде далі, кажучи, що "посилання на const не може мутувати", що є набагато більш надійною гарантією. Для цього на Java внутрішній стан повинен бути остаточним і визначатися під час будівництва. Const набагато простіший у використанні, а вже існуючий об’єкт може бути "просунутий" у посилання const.

Так, ви повинні використовувати const, коли це можливо. Він укладає договір, що ваш код щось не змінить. Пам'ятайте, що не-const змінна може бути передана функції, яка приймає параметр const. Ви завжди можете додати const, але не забирати його (не без const акторів, що дуже погана ідея).

Правильність споруди часом може бути виснажливою, але це допомагає гарантувати незмінність. Це має вирішальне значення для багатопотокового коду, де потоки діляться об'єктами. Це робить певні завдання більш ефективними: замість того, щоб копіювати стан, просто повторно використовуйте той самий незмінний об’єкт. Бібліотеки можуть приймати параметри const, щоб гарантувати програмісту, що ні, ваш об'єкт не зміниться непередбачувано в чорній дірі, що є кишкою бібліотеки.


1
Голосуйте вгору, тому що ви пояснюєте це finalі constне маєте однакових гарантій.
Двері Білла

2
Стійкість - це можливість запису, а не змінність.
Василевс

@Basilevs, що станеться, якщо ви пишете об’єкт? Він мутує. Як ви мутуєте об’єкт? Пишіть їй.

4
Що станеться, якщо ви напишете на посилання const? Помилка часу компіляції. Що станеться, якщо ви запишете до об'єкта, на який десь посилається посилання const, через іншу неконтрастну посилання? Він мутує. Незмінюваний об’єкт не може мутувати, отже, const референс не обов'язково посилається на незмінний об'єкт.
Василевс

@Basilevs ваші спостереження стосуються лише const refs. Якщо сам об'єкт оголошений const (не лише посиланням), він є більш-менш непорушним (якщо хтось не прикро відкидає незграбність).
Меттью Джеймса Бріггса

5

Особисто constмені потрібно зовсім небагато часу для написання і дуже мало часу для читання, як правило, набагато менше, ніж потрібно, щоб перевірити, чи який-небудь код мутує змінна, і це насправді заважає мені писати помилки (хто-небудь коли-небудь збільшував свій кінцевий ітератор випадково? І т.д.

Я також вважаю, що суворість у використанні const спрямовує мене на кращий код іншими способами, як, наприклад, створення допоміжних функцій для нетривіальної ініціалізації.


4

Я збираюся не погоджуватися з іншими плакатами і рекомендую не використовувати верхній рівень constдля локальних змінних та параметрів. (Посилання та покажчики на const, тобто const T&різні, і ви повинні використовувати їх для коректності в усі часи, коли це доречно.)

Перевагами вищого рівня constє:

  • Зрозуміло, що локальні змінні не мутуються.
  • Припускає помилку компілятора, якщо ви випадково намагаєтесь їх вимкнути.

Недоліками є:

  • Візуальне захаращення.
  • Не можна використовувати для змінних "pseudo-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використовували багато, і я вважав, що це зовсім не корисно, але він наповнив код тонкими песимізаціями, як зазначено вище. Я особисто вважаю за краще застосовувати загальну політику щодо зміни змінних якомога рідше, а також робити функції досить малі, щоб використання змінної було очевидно, і навіть якщо вона модифікована, складність функції є достатньо низькою, щоб зробити її не -проблема.


2
Ваша думка щодо переїзду - показує, де ви не використовуєте локальну систему const, як ви (маєте намір) модифікувати її з переміщенням
Caleth

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

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

2

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

  • Простіше читати код. Коли хтось читає декларацію змінної, вона знає, що вона не зміниться. Ще одна менша річ, яка переживає, читаючи код.
  • Запобігайте випадковому зміні змінної
  • Жодного строку виконання штрафу, все перевіряється статично. Це як безкоштовний обід, constдля написання потрібно зайняти лише секунду, так що це не велика справа.
  • Завжди корисно вносити змінні / параметри у багатопотокові програми. Навіть ваша заявка не є багатопоточною, це все-таки хороша звичка.
  • Ви даєте можливість компілятору C ++ оптимізувати ваш код.

Зауважте, що тут немає правильної / неправильної відповіді. У вашому посиланні відповідь, у якого було найбільше аргументів, finalне повинен використовуватися локально. Однак наступний відповідь настійно рекомендував це.

Якщо ваша функція проста і тривіальна , ви не повинні додавати її, constоскільки всі розуміють ваш намір. Однак якщо логіка у вашій функції нетривіальна, вам слід скористатися ключовим словом. Пам'ятайте, що втратити мало.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.