Чи є читабельність поважною причиною не використовувати const у (еталонних) параметрах?


24

Під час написання деяких функцій я знайшов ключове слово const у таких параметрах:

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
}

часто викликає розбиття рядка на 2 рядки в IDE або vim, тому я хочу видалити всі ключові слова const у параметрах:

void MyClass::myFunction(MyObject& obj,string& s1,string& s2,string& s3){
} 

це поважна причина не використовувати const? Чи можна підтримувати об'єкти параметрів незмінними вручну?


110
"Гей, я хочу функціонально змінити свою програму", щоб зробити її більш читаною - це погана погана причина.
Пітер Б

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

43
Кращий спосіб поліпшити читабельність - зменшити кількість аргументів.
5gon12eder

15
"const", можливо, покращує читабельність. Це твердження дає зрозуміти, що obj може не змінитися!
Чарльз

14
Що допоможе читабельності - додавання пробілу після кожної коми.
sam hocevar

Відповіді:


182

Читання - вагомий привід навчитися використовувати пробіли:

void MyClass::myFunction(
        const MyObject& obj,
        const string& s1,
        const string& s2,
        const string& s3
) {
    return;
}

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

constщось означає. Не кидайте це лише тому, що у вас немає місця та ідей. Читання - це король, але ламати речі в його імені - це просто здаватися.


6
"вам не доведеться переставляти їх, коли ви зміните ім'я myFunction" - хоча в цьому випадку це виглядає так, ніби вони розміщені приблизно в одному рядку з відкриттям (, і якщо це так, то, можливо, вам доведеться перестановити їх, якщо довжина назви класу + функції змінюється більш ніж приблизно на 4 символи. Тож якщо ви не хочете цього робити, додайте фіксовану кількість рівнів відступу, а не число, яке залежить від довжини назви функції. Я б рекомендував 1 рівень, у цій відповіді використовується 6, але будь-яке фіксоване число досягає заявленої мети :-)
Стів Джессоп

6
@CandiedOrange Я здивований, що ви не використовували "форму 6" у цій відповіді ... це явно менш некрасиво!
svidgen

6
Форма 6 на виграш. Один простір вкладок для одного рівня відступу. Простий і ефективний. Проблема вирішена :)
Гонки легкості з Монікою

2
Гаразд добре форма 6 це. Це варіант, про який згадував Джеффрігг на c2.
candied_orange

4
@ random832 Я думаю, що ми впевнено перебуваємо на території, що пролягає на велосипедах. Ось правильний спосіб вирішити це питання: шукайте приклади коду для пошуку прикладів, зверніться до посібника зі стилю магазинів, запитайте розробників у вашому магазині, і якщо жодне з цього не дає авторитетної відповіді, використовуйте це. Вирішіть суперечки, які можуть піти в будь-якому випадку з чвертю. Як тільки чверть заговорить, будьте послідовними!
candied_orange

52

Власне, питання читабельності, безумовно, йде в іншому напрямку. По-перше, ви можете тривіально вирішити лінію запуску за допомогою пробілів . Але вилучення constне просто скоротить рядок, але повністю змінює значення програми.

Герб Саттер відноситься до constпо відношенню до constяк найважливіше,const оскільки посилання на нього constможе пов'язуватися з тимчасовим та продовжувати його термін експлуатації. Посилання lvalue на non- constне може, вам потрібна окрема змінна.

void foo_const(std::string const& );
void foo_nc(std::string& );

std::string some_getter();

foo_const(some_getter());      // OK
foo_const("Hello there"); // OK

foo_nc(some_getter()); // error
foo_nc("Nope");   // error

std::string x = some_getter(); // have to do this
foo_nc(x);                     // ok
std::string msg = "Really??";  // and this
foo_nc(msg);                   // ok

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


6
Ваш другий пункт дає мені головний біль , намагаючись з'ясувати , якщо constмає в увазі constчи до іншого , constі що constнасправді найголовнішеconst
Mindwin

3
@Mindwin Я думаю, що іронія полягає в тому, що мій другий абзац зрозумілий і однозначний, і я не маю поняття, про що ти говориш.
Баррі

2
@Barry Це, безумовно, однозначно, але мені знадобилося кілька прочитань цього пункту, щоб спробувати зрозуміти, що це означає. Я думаю, що проблема полягає в тому, що вона може бути розібрана "Herb Sutter відноситься до const (стосовно посилання на const) як до найважливішого const ..." або "Herb Sutter відноситься до const в (посилання на const) як до найбільш важливий const ... "Я вважаю, що останнє є єдиним правильним угрупуванням слів, але для його обробки потрібно трохи. Можливо, є спосіб використовувати лапки, щоб усунути неоднозначність?
Корт Аммон - Відновіть Моніку

1
Я думаю, що деякі дефісні сполуки очистять це.
shawnt00

2
або спеціально використовувати, const&а не посилатися на constяк іменник (-фраза) там
Калет

21

Проста відповідь - «ні».

Довга відповідь полягає в тому, що constключове слово є частиною договору, який пропонує функція; це говорить вам, що аргумент не буде змінено. Щойно ви знімаєте constгарантію, виходить з вікна. Пам'ятайте , що ви не можете розумно підтримувати константність (або будь-яке інше майно) чого - або з використанням документації, конвенції або керівних принципів - якщо константность не виконується компілятором, хто - то буде думати , що вони можуть зробити їх роботу легше , якщо вони возитися з параметр "ще трохи". Поміркуйте:

// parameter "foo" is not modified
void fna(Foo& foo);

void fnb(const Foo& foo);

Окрім того, що остання версія є більш стислою, вона також забезпечує більш сильний контракт і дозволяє компілятору допомогти вам підтримувати свої наміри. Перший не робить нічого, щоб перешкодити fna(Foo&)функції змінити параметр, який ви переходите до нього.

Як і у відповіді @CandiedOrange, ви можете використовувати пробіл, щоб викласти код і підвищити читабельність.


14

Видалення constключового слова знімає читабельність, оскільки constпередає інформацію читачеві та компілятору.
Скорочення горизонтальної довжини коду добре (нікому не подобається прокручування в бік), але constтекст більше, ніж текст. Ви можете переписати його:

typedef string str;
typedef MyObject MObj;
void MyClass::myFunction(const MObj& o,const str& s1,const str& s2,const str& s3)

Що не змінює контракт, але відповідає потребі скоротити довжину лінії. По-справжньому, я вважав би описаний вище фрагмент менш читабельним і вирішив би використовувати більше пробілів, як уже було сказано у відповіді CandiedOrange.

const- це функціональність самого коду. Ви не зробили б функцію не членом видаляти MyClass::розділ декларації, тому не видаляйтеconst


4
Я погоджуюсь, що наданий вами фрагмент менш читабельний. Це змушує читача піти дізнатися, що MObjі strє, і , безумовно , піднімає брови. Це особливо дивно для типів , чиї імена у вас вже є контроль над: Наприклад , чому ти просто не назвати , MyObjectяк MObjпочати?
Джейсон C

3

Чи є читабельність поважною причиною не використовувати const в параметрах?

Ні. Відмова constможе змінити функціональність, втратити захист constі може потенційно створити менш ефективний код.

Чи можна підтримувати об'єкти параметрів незмінними вручну?

Замість того, щоб витрачати час вручну на формування коду

void MyClass::myFunction(const MyObject& obj,const string& s1,const string& s2,const string& s3){
  //
}

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

void MyClass::myFunction(const MyObject& obj, const string& s1, const string& s2, 
    const string& s3) {
  // 
}

-1

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

Якщо я бачу багато аргументів у методі, це змушує мене розглянути питання створення jaron на базі проекту (Matrix, Employee, Rectangle, Account), який був би набагато коротшим, простішим для розуміння (виключає довгий список аргументів методів).


Домовились. Я вагався вказати на це. Таким чином, "крайній випадок".
чорніє

@cmaster Тим не менш, іноді в певних контекстах із певними програмістами це може бути читабельним. Наприклад, у дуже конкретному випадку програмної заглиблення у викликах API Windows, із зчитувачем, який звик до цього середовища, такі речі, як, наприклад, typedef Point * LPPOINTі typedef const Point * LPCPOINT, хоча це дуже недоброзичливо, все ще несе в собі неявне значення, оскільки воно відповідає негайним очікуванням в контексті. Але ніколи в загальному випадку; це просто дивний виняток, про який я можу придумати.
Джейсон С

1
Так, коли я побачив питання, "const unsigned long long int" мені прийшло в голову, але це не хороший кандидат, щоб отримати користь від того, щоб бути "const" або "reference". Typedef вирішує загальну проблему скорочення назв; але не здається гарним дизайном приховувати саме цілі мовних конструкцій (як-от "const") за нею.
чорніє
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.