There'a горстка ситуаций, что стандарт C++ приписывает как неопределенное поведение. Например, если я выделяю с new[]
, затем попытайтесь освободить с delete
(нет delete[]
) это - неопределенное поведение - что-либо может произойти - оно могло бы работать, оно могло бы отказать злобно, оно могло бы повредить что-то тихо и посадить синхронизированную проблему.
Это настолько проблематично для объяснения этого, что-либо может произойти часть с новичками. Они начинают "доказывать", что "это работает" (потому что это действительно работает над реализацией C++, которую они используют), и спросите, "что могло возможно быть неправильным с этим"? Какое краткое объяснение я мог дать, который мотивировал бы их только к не, пишут такой код?
«Поздравляю, вы определили поведение компилятора для этой операции. Я ожидаю, что отчет о поведении других 200 компиляторов, существующих в мире, покажет будь у меня на столе к 10:00 завтра. Не разочаровывай меня сейчас, твое будущее выглядит многообещающим! "
Расскажите им о стандартах и о том, как разрабатываются инструменты для соответствия стандартам. Все, что выходит за рамки стандарта, может работать или не работать, например UB.
Включить malloc_debug и удалить
массив объектов с деструкторами. free
ing указатель внутри блока должен выйти из строя. Вызовите их все вместе и продемонстрируйте это.
Нужно придумать другие примеры, чтобы построить свою достоверность до тех пор, пока они не поймут, что они новички, и что о С++ нужно знать очень много.
Один был бы...
"Это" использование не является частью языка. Если бы мы сказали, что в этом случае компилятор должен сгенерировать код, который ломается, то это была бы особенность, какое-то требование к производителю компилятора. Авторы стандарта не хотели давать ненужную работу над "особенностями", которые не поддерживаются. Они решили не предъявлять никаких поведенческих требований в таких случаях.
Скомпилируйте и запустите эту программу:
#include <iostream>
class A {
public:
A() { std::cout << "hi" << std::endl; }
~A() { std::cout << "bye" << std::endl; }
};
int main() {
A* a1 = new A[10];
delete a1;
A* a2 = new A[10];
delete[] a2;
}
По крайней мере, при использовании GCC он показывает, что деструктор вызывается только для одного из элементов при однократном удалении.
О однократном удалении на POD Укажите им FAQ по C ++ или попросите их запустить свой код через cppcheck .
C ++ на самом деле не является языком для дилетантов, и простое перечисление некоторых правил и их беспрекословное подчинение приведет к ужасным программистам; Большинство самых глупых вещей, которые, как я вижу, люди говорят, вероятно, связаны с таким слепым следствием правил / юристом.
С другой стороны, если они знают, что деструкторы не будут вызваны и, возможно, возникнут другие проблемы, они постараются этого избежать. И, что более важно, есть шанс отладить его, если они когда-нибудь это сделают случайно, а также иметь шанс осознать, насколько опасными могут быть многие функции C ++.
Поскольку есть много поводов для беспокойства, ни один курс или книга никогда не заставят кого-то освоить C ++ или, возможно, даже так хорошо освоить его.
Тихо переопределите new, new[], delete и delete[] и посмотрите, сколько времени ему потребуется, чтобы заметить ;)
Если это ... просто скажите ему, что он не прав и укажите ему на C++ spec. О да ... и в следующий раз будьте более осторожны при найме людей, чтобы избежать "дырок"!
Есть две предпосылки для хорошей соли: она должна быть длинной и случайной. Для этого есть много способов. Например, можно использовать комбинацию microtime
и rand
, но можно использовать еще большую длину для обеспечения уникальности соли.
Хотя вероятность столкновения невелика, имейте в виду, что хэширование вашей соли с помощью MD5 или других алгоритмов, подверженных столкновению, уменьшит вероятность того, что ваша соль является уникальной без всякой причины.
EDIT: Замените rand ()
на mt _ rand ()
. Как отметил Майкл, это лучше, чем ранд
.
Перед добавлением можно проверить list.contains () .
if(!list.contains(value)) {
list.add(value);
}
Я предположил, что это будет очевидно! Однако добавление предметов в HashSet и последующее создание списка из этого набора было бы более эффективным.
-121--1266684-Позвольте им попробовать себя, пока их код не потерпит крах во время теста. Тогда слова не понадобятся.
Дело в том, что у новичков (мы все были там) есть некоторое эго и уверенность в себе. Все в порядке. На самом деле, ты не можешь быть программистом, если не будешь. Важно воспитывать их, но не менее важно поддерживать их и не сокращать их начало в путешествии, подрывая их доверие к себе. Просто будьте вежливы, но доказывайте свою позицию фактами, а не словами. Будут работать только факты и доказательства.
Я бы объяснил, что если бы они написали код неправильно, то их следующий обзор производительности не был бы счастливым. Этого достаточно "мотивации" для большинства людей.
Мне приходят на ум две возможности:
Вы могли бы спросить их: «Если бы вы могли проехать по шоссе в противоположном направлении в полночь и выжить, вы бы сделали это регулярно?»
Более сложное решение могло бы быть чтобы настроить другую среду компилятора / запуска, чтобы показать им, как она терпит неудачу при различных обстоятельствах.
вместо этого можно использовать http://msdn.microsoft.com/en-us/library/system.windows.forms.screen.primaryscreen.aspx
-121--1517186-, используя функцию boost:: assign.
vector<int> values;
values += 1,2,3,4,5,6,7,8,9;
-121--1786978- Просто цитируем из стандарта. Если они не могут принять это, они не программисты C++. Отрицали бы христиане Библию?; -)
1,9 Исполнение программы
Семантические описания в этом Международном стандарте определяют параметризованную недетерминированную абстрактную машину. [...]
Некоторые аспекты и операции абстрактной машины описаны в этом Международном стандарте как , определенные при внедрении (например, sizeof (int)
). Они составляют параметры абстрактной машины. Каждая реализация должна включать документацию, описывающую ее характеристики и поведение в этих отношениях . [...]
Некоторые другие аспекты и операции абстрактной машины описаны в настоящем Международном стандарте как неуказанные (например, порядок оценки аргументов функции). По возможности этот Международный стандарт определяет набор допустимых вариантов поведения . Они определяют недетерминированные аспекты абстрактной машины. [...]
Некоторые другие операции описаны в этом Международном стандарте как undefined (например, эффект дереференции нулевого указателя). [Примечание: настоящий Международный стандарт не предъявляет никаких требований к поведению программ, которые содержат неопределенное поведение . - end note]
Вы не можете получить больше ясности.
Мне нравится эта цитата:
Неопределенное поведение: оно может повредить ваши файлы, отформатировать диск или отправить письмо ненависти вашему боссу .
Я не знаю, кому это приписать (может быть, это из Effective C ++ )?
Короче говоря, вы не можете использовать sizeof() для структуры, элементы которой не были определены, а если вы это сделаете, то вы не можете использовать sizeof() для структуры, элементы которой не были определены. а если вы это сделаете, демоны могут вылететь из вашего носа.
"Демоны могут вылететь из вашего носа" просто должно быть частью словарного запаса каждого программиста.
Более того, поговорите о переносимости. Объясните, как часто программы приходится переносить на разные ОС, не говоря уже о разных компиляторах. В реальном мире переносы обычно выполняются людьми, не являющимися программистами. Некоторые из этих переносов осуществляются даже на встроенные устройства, где могут быть огромные затраты, связанные с обнаружением того, что компилятор решил иначе, чем вы предполагали.
Неопределенный означает явно ненадежный. Программное обеспечение должно быть надежным. Больше ничего говорить не нужно.
Замерзший пруд - хороший пример неопределенной поверхности для ходьбы. То, что вы один раз прошли по нему, не означает, что вы должны добавить этот короткий путь в свой бумажный маршрут, особенно если вы планируете четыре времени года.
То, что их программа кажется работающей, ничего не дает; компилятор может генерировать код, который работает (как вы вообще определяете «работу», когда правильное поведение undefined ?) в будние дни, но форматирует ваш диск по выходным. Читали ли они исходный код в свой компилятор? Изучить их дизассемблированный вывод?
Или напомнить им, что тот факт, что он «работает» сегодня, не гарантирует его работы при обновлении версии компилятора. Скажите им, чтобы они повеселились, находя в этом незаметные ошибки.
И действительно, почему , а не ? Они должны предоставить обоснованный аргумент в пользу использования неопределенного поведения, а не наоборот. Какая причина использовать delete
вместо delete []
, кроме лени? (Хорошо, есть std :: auto_ptr
. Но если вы используете std :: auto_ptr
с массивом, выделенным new []
, вам, вероятно, следует в любом случае использовать std :: vector
.)