Замечания:
class A
имеет объект class B
в качестве члена или наоборот. Читайте FAQ:
Я предполагаю, что вы приходите с Java или Java-подобного языка, где, когда вы выходите из границы массива, вы получаете исключение «index index out of bounds».
Ну, C ожидает от вас большего; он экономит пространство, которое вы просите, но он не проверяет, выходите ли вы за пределы этого накопленного пространства. Как только вы это сделаете, как указано выше, у программы есть такое ужасное неопределенное поведение.
И помните о будущем, если у вас есть ошибка в вашей программе, и вы не можете ее найти, и когда вы перейдите код / отлаживайте его, все кажется ОК, есть хороший шанс, что вы «вне пределов» и доступ к нераспределенному месту.
Потому что неопределенное поведение == все может случиться. Вам не повезло, что это не сбой, такое поведение может потенциально скрывать ошибки.
Что касается a
, определяющего дважды - это ошибка в компиляторе.
компиляторы с хорошим анализом кода, безусловно, будут предупреждать о том, что код ссылается за пределы вашего распределения массива. забыв о множественном объявлении, если вы его запустили, он может или не может быть неисправен (неопределенное поведение, как говорили другие). если, например, у вас есть страница с кучей на 4 Кбайт (в адресном пространстве процессора), если вы не пишете вне этой страницы, вы не получите ошибку от процессора. после удаления массива, если вы это сделали, и в зависимости от реализации кучи куча может обнаружить, что она повреждена.
Объявление двух переменных, называемых a
, безусловно, является ошибкой; если ваш компилятор соглашается с этим, тогда он сломан. Я предполагаю, что вы имеете в виду, что вы по-прежнему не получаете ошибку, если вы замените одно объявление другим.
Доступ к массиву не проверен диапазоном. Во время компиляции размер массива часто неизвестен, и язык не требует проверки даже тогда, когда он есть. Во время выполнения проверка снизит производительность, что противоречит философии C ++, которая не платит за то, что вам не нужно. Таким образом, доступ за пределами массива дает неопределенное поведение, и программист должен убедиться, что этого не происходит.
Иногда недопустимый доступ вызывает ошибку сегментации, но это не гарантируется , Как правило, защита памяти применяется только к целым страницам памяти с типичным размером страницы в несколько килобайт. Любой доступ на странице действительной памяти не будет обнаружен. Существует хорошая вероятность, что доступная вам память содержит какую-либо другую программную переменную или часть стека вызовов, поэтому запись может повлиять на поведение программы практически так, как вы можете себе представить.
Если вы хотите быть безопасным, вы можете использовать std::vector
и получать доступ только к его элементам, используя функцию at()
. Это проверит индекс и выдаст исключение, если оно выходит за пределы допустимого диапазона. Он также будет управлять распределением памяти для вас, исправляя утечку памяти в вашем примере.