Семинар 3 (18.09.2015)

Как "правильно" писать программы на C++ (часть 1)

Один из наиболее важных принципов при программировании на C++ можно сформулировать следующим образом:

не смешивайте C и C++.

Несмотря на то, что язык C++ позволяет так делать, и то, что программа на C почти всегда является валидной программой на C++, на практике такое смешивание приводит к запутыванию кода и ошибкам.

Как понять, что вы смешиваете два языка?

Небольшой пример, демонстрирующий сложности при работе с указателями:

void doSomeWork() {
    // Никогда так не пишите!
    // 1. оператор new - надо не забыть в конце сделать delete
    std::string * str = new std::string("hello world");

    if (str->find('o') != std::string::npos) {
        // 2. Ещё одна точка выхода из функции - нужно удалить str:
        delete str;
        return
    }

    // Вызов функции, что будет если она выбросит исключение?
    // Можно конечно обернуть её в try-catch (или обернуть всё в try-catch)
    // Но выглядеть будет не очень аккуратно
    doSomeOtherWork();

    if (str->size() > 10) {
        // Ещё одна точка выхода. Это начинает напоминать тот хаос,
        // который был с управлением ресурсами в C.
        delete str;
        return;
    }

    delete str;
}

Ещё один пример:

char * getSomeString();

// ...

char * str = getSomeString();
// do something with str...
// Нужно ли удалять память при помощи free или это указатель на статически
// аллоцированный участок памяти? Может быть нужно удалять при помощи какой-то другой функции?
// free(str);

// Лучше так:
std::string getSomeString();
    int * list = new int[5]{1, 2, 3};
    for (int i=0; i<5; i++) {
        std::cout << list[i] << std::endl;
    }
    delete[] list;

однако предпочтительнее (то есть, используйте всегда :) ) использовать std::vector.

    std::vector<int> v = {1, 2, 4, 8};
    for (int i=0; i<v.size(); i++) {
        std::cout << v[i] << std::endl;
    }

В целом же, использование вектора мало отличается от использования массива:

    std::vector<int> v(5); // вектор длины 5
    v[3] = 13;
    for (int i=0; i<v.size(); i++) {
        std::cout << v[i] << std::endl;
    }