Программирование. Принципы и практика использования C++ Исправленное издание, стр. 248
// инициализируются нулемdouble ad[100] = { }; // все элементы инициализируются нулемchar chars[] = { 'a', 'b', 'c' }; // нет завершающего нуля!Обратите внимание на то, что количество элементов в массиве
aicharsai2ad18.5.4. Проблемы с указателями
Как и массивами, указателями часто злоупотребляют. Люди часто сами создают себе проблемы, используя указатели и массивы. В частности, все серьезные проблемы, связанные с указателями, вызваны обращением к области памяти, которая не является объектом ожидаемого типа, причем многие из этих проблем, в свою очередь, вызваны выходом за пределы массива. Перечислим эти проблемы.
• Обращение по нулевому указателю.
• Обращение по неинициализированному указателю.
• Выход за пределы массива.
• Обращение к удаленному объекту.
• Обращение к объекту, вышедшему из области видимости.
На практике во всех перечисленных ситуациях главная проблема, стоящая перед программистом, заключается в том, что внешне фактический доступ выглядит вполне невинно; просто указатель ссылается на неправильное значение. Что еще хуже (при записи с помощью указателя), проблема может проявиться намного позднее, когда окажется, что некий объект, не связанный с программой, был поврежден. Рассмотрим следующий пример.
int* p = 0;*p = 7; // Ой!Очевидно, что в реальной программе это может произойти, если между инициализацией и использованием указателя размещен какой-то код. Чаще всего эта ошибка возникает при передаче указателя p функции или при получении его в результате работы функции. Мы рекомендуем никуда не передавать нулевой указатель, но, уж если вы это сделали, проверьте указатель перед его использованием. Например,
int* p = fct_that_can_return_a_0();if (p == 0) { // что-то делаем}else { // используем р *p = 7;}и
void fct_that_can_receive_a_0(int* p){ if (p == 0) { // что-то делаем } else { // используем р *p = 7; }}Основными средствами, позволяющими избежать ошибок, связанных с нулевыми указателями, являются ссылки (см. раздел 17.9.1) и исключения (см. разделы 5.6 и 19.5).
int* p;*p = 9; // Ой!В частности, не забывайте инициализировать указатели, являющиеся членами класса.
int a[10];int* p = &a[10];*p = 11; // Ой!a[10] = 12; // Ой!Будьте осторожны, обращаясь к первому и последнему элементам цикла, и постарайтесь не передавать массивы с помощью указателей на их первые элементы. Вместо этого используйте класс
vector
int* p = new int(7);// ...delete p;// ...*p = 13; // Ой!Инструкция
delete p*pnewdeletenewdeleteVector_ref
int* f(){ int x = 7; // .. . return &x;}// ...int* p = f();// ...*p = 15; // Ой!Возврат из функции
f()*p