Рекомендации по написанию кода в C++ (часть 2)

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

    1. Избегайте магических чисел в программе, это кстати частный случай из предыдущего примера.
      Суть его вот в чем, например, в операторе if сравнение можно было бы сделать так:

      if (8 == currentMonth) {
      
      }

      Но у человека, который первый раз видит ваш код сразу возникнет вопрос, что это за магическое число 8? Конечно в данном примере не сложно догадаться, что значит восемь, но даже если и так, какой в этом смысл? Другое дело, если бы код выглядел так:

      const int august = 8;
      
      if ( august == currentMonth) {
              cout << "Current month - august";
      }

      По имени переменной понятно, что 8 — это порядковый номер месяца, все предельно ясно и просто. 

    2. В условиях сравнивайте константное значение со значением переменной, а не наоборот.
      Данная рекомендация немного усложняет понимание кода, но зато предотвращает появление ошибок времени компиляции. Вернемся все к тому же примеру из пункта 5. Вот фрагмент кода:

      if (august == currentMonth) {
      }

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

      if (currentMonth == august) {
      }
    3. Всегда выполняйте начальную инициализацию переменных.
      Соблюдение этой рекомендации поможет сэкономить вам кучу времени. Пример из жизни:

      #include <iostream>
      using namespace std;
      int main()
      {
          int sum = 0;
          for(int i = 0; i < 5; i++) {
              sum++;
          }
          cout << sum;
          return 0;
      }

      В переменной sum в цикле накапливается сумма. Программа хорошо работает, проверьте. Заметьте, что переменной sum при объявлении был присвоен нуль, это и есть начальная инициализация. Тот же пример но без начальной инициализации:

      #include <iostream>
      using namespace std;
      int main()
      {
          int sum;
          for(int i = 0; i < 5; i++) {
              sum++;
          }
          cout << sum;
          return 0;
      }

      Результат будет неправильный, так как небыло начальной инициализации, соответственно и сумма будет неправильной. 

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

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

    // фрагмент кода 
    for(int i = 0; i < 5; i++) {
        sum++;
    }

    Управляющая переменная i объявлена внутри цикла, это значит то, что область её видимости ограничивается областью видимости цикла. С точки зрения физических процессов в памяти, это значит, что когда цикл завершится, память отводимая под переменную i — освободится, а сама переменная i будет удалена. Это процесс полностью обоснован, ведь цикл закончился и переменная уже не нужна, так зачем же она будет занимать память. Тот же пример, но в нем переменная i будет объявлена вне цикла. Этот пример я не придумал, я его часто встречаю в жизни, почему-то некоторым программистам нравится делать так:

    int i;
    for(i = 0; i < 5; i++) {
        sum++;
    }

    или

    int i = 0;
    for(; i < 5; i++) {
        sum++;
    }

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

    int i = 0;
    for(; i < 5; i++) {
        sum++;
    }
    
    int i = 0;
    for(; i < 5; i++) {
        sub--;
    }

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

    main.cpp:14: error: redeclaration of ‘int i’

    Но если бы циклы были построены так, то ошибок бы не было:

    for(int i = 0; i < 5; i++) {
        sum++;
    }
    for(int i = 0; i < 5; i++) {
        sub--;
    }

    И память высвобождается в таком случае правильно.

Если вы до конца внимательно прочитали эту статью, можно считать, что качество вашего кода отныне стало лучше, хотя бы, на чуть чуть. И теперь, когда вы приступите к написанию своей очередной программы, не забудьте применять на практике все те приемы, о которых вы прочитали в этой и предыдущей статьях. Если вы хотите изучить более подробно стандартизации в С++, прочитайте книгу «Стандарты программирования на С++ Герб саттер и Андрей Александреску».

Автор: Marienko L.
Дата: 31.12.2013
Поделиться:

Комментарии

  1. Gosha

    По поводу пункта 5. Некоторые пишут на обычном СИ без плюсов. В СИ нельзя объявить переменную в любом месте. И по-другому цикл сделать просто невозможно.

  2. ds

    В пункте 3 опечатка в слове сумма:
    Результат будет не правильный, так как не было начальной инициализации, соответственно и сума будет не правильной.

  3. Сергей Клементьев

    В тексте Вы назвали месяц ougest. Может имелось ввиду august?

Оставить комментарий

Вы должны войти, чтобы оставить комментарий.