Забыл упомянуть о способе борьбы с неожиданными перераспределениями памяти в std::vector. Есть метод std::vector::reserve который позвляет зарезервировать необходимое количество памяти заранее, например если известно примерное число элементов, которые будут храниться в векторе:
Метод std::vector::capacity позволяет понять сколько элементов можно положить в вектор без перераспределения памяти.
Об использовании алгоритмов
На самом деле, использование STL (и им подобных) алгоритмов кажется через чур запутанным или, возможно неуместным, не всем новичкам в C . Тут все дело в менталитете — для тех кто переходит на C с C, Pascal или Java обобщенное программирование может показаться трюком «для гуру» который только нарушает читаемость программ. Для тех же, кто имеет опыт в функциональных языках типа LISP или Scheme, или, хотя бы, Python или Ruby, возможности обобщенного программирования в C могут показаться весьма скудными.
NVI Idiom и «стандартная» практика программирования
Мне был задан вопрос: откуда свалилась это правило использовать невиртуальные функции в интерфейсе класса, а виртуальные только в закрытых и защищенных секциях и что, например в Java, давно существует подход определенно другой. Я про Java много что наговорил, кроме главного. Главное в том, что независимо от того насколько плох или хорош Java или C , имея много общего, во многом они различаются по стилю программирования (т.е. идиоматически). Во многих случаях нельзя прямо руководствоваться своим опытом программирования на Java в C (и наоброт) и это должно быть очевидно: в Java нет деструкторов, есть сборка мусора и все классы автоматически наследуют Object. Это и многое другое вносит существенные коррективы.
Поэтому существуют, скажем ОО паттерны (общие для многих ОО языков программирования) и идиомы, специфичные к одному.
Что касается NVI – то это скорее идиома, однако существует родственный паттерн — Template Method, который успешно применяется в Java.
Было несколько вопросов и реплик относительно безопасности программ, безопасности языков программирования и т.п. Я бы хотел высказать свое мнение на свежую голову, при этом никоим образом не пытаюсь навязать его как авторитетное.
Итак,
Качественное ПО – это то ПО, которое удовлетворяет поставленным требованиям. И в конечном итоге удовлетворяет пользователя.
Надежное ПО – это программы, которые мало подвержены к отказам. Т.е. программа ведет себя предсказуемо и валидно (согласно требованиям) даже в случаях, когда переданы неверные данные на вход, нехватает ресурсов и т.п.
Есть также понятие времени наработки на отказ, у надежного ПО оно должно быть достаточно (или очень) велико.
Под безопасным кодом я подразумеваю прежде всего код, продуктом которого является надежное ПО.
Все это я написал не заглядывая в словари, спец литературу и т.п., поэтому прошу меня исправить, если что.
Теперь о безопасности языков программирования. Далее приводится цитата из книги <<Дизайн и эволюция языка C >> (раздел 14.2.4), которая мне кажется кое что может прояснить:
Хорошие программы – это продукт хорошего образования, удачного проектирования, адекватного тестирования и т.д., а не наличие в языке средств, которые предположительно должны использоваться только «правильно». Употребить во вред можно любое средство, поэтому вопрос не в том, можно ли чем-то воспользоваться неправильно (можно!) или будут ли этим неправильно пользоваться (будут!). Вопрос в том, необходимо ли данное средство при условии его правильного употребления настолько, чтобы оправдать затраты на его реализацию, удастся ли смоделировать его с помощью других средств языка и реально ли с помощью обучения обратить во благо неправильное использование.
3 Окт 2006
Вопрос про строковый литерал
Вопрос: Что является константным в выражении const char str[] = String literal; массив или char? Ответ: Конечно char.
Вот текст из Страуструпа:
The type of a string literal is array of the appropriate number of cons characters, so Bohr is of type const char [5].
A string literal can be assigned to a char*. This is allowed because in previous definitions of C and C, the type of a string literal was char*. Allowing the assignment of a string literal to a char* ensures that millions of lines of C and C remain valid.
Вопрос про ошибку компиляции (личный)
Сев в автобус, я вдруг понял, что совершенно зря пообещал побить костылем одного господина. Дело в том, что вопрос был совершенно законным. Дело в порядке поиска имен. Компилятор ищет функцию, которую следует вызвать в каждом конкретном случае, среди доступных областей видимости в определенном порядке. Область видимости имен класса является одним из первых кандидатов для поиска. Когда компилятор находит функцию (или несколько) с соответствующим именем (независимо от параметров), поиск прекращается.
В конкретном случае, класс, по всей видимости, содержал функцию f(int*) с искомым именем, но другими параметрами. Не найдя других кандидатов внутри класса, компилятор остановил поиск и сообщил об ошибке.