*p_auto_int = 1024;
Если auto_ptr ни на что не указывает, то как заставить его адресовать что-либо? Другими словами, как мы можем присвоить значение внутреннему указателю объекта auto_ptr? Это делается с помощью операции reset(). Например:
else
// хорошо, присвоим ему значение
p_auto_int.reset( new int( 1024 ) );
Объекту auto_ptr нельзя присвоить адрес объекта, созданного с помощью оператора new:
void example() {
// инициализируется нулем по умолчанию
auto_ptr int pi;
{
// не поддерживается
pi = new int( 5 ) ;
}
}
В этом случае надо использовать функцию reset(), которой можно передать указатель или 0, если мы хотим обнулить объект auto_ptr. Если auto_ptr указывает на объект и является его владельцем, то этот объект уничтожается перед присваиванием нового значения внутреннему указателю auto_ptr. Например:
auto_ptr string
pstr_auto( new string( "Brontosaurus" ) );
// "Brontosaurus" уничтожается перед присваиванием
pstr_auto.reset( new string( "Long-neck" ) );
В последнем случае лучше, используя операцию assign(), присвоить новое значение существующей строке, чем уничтожать одну строку и создавать другую:
// более эффективный способ присвоить новое значение
// используем операцию assign()
pstr_auto-assign( "Long-neck" );
Одна из трудностей программирования состоит в том, что получить правильный результат не всегда достаточно. Иногда накладываются и временные ограничения. Такая мелочь, как удаление и создание заново строкового объекта, вместо использования функции assign() при определенных обстоятельствах может вызвать значительное замедление работы. Подобные детали не должны вас беспокоить при проектировании, но при доводке программы на них следует обращать внимание.
Шаблон класса auto_ptr обеспечивает значительные удобства и безопасность использования динамически выделяемой памяти. Однако все равно надо не терять бдительности, чтобы не навлечь на себя неприятности:
* • нельзя инициализировать объект auto_ptr указателем, полученным не с помощью оператора new, или присвоить ему такое значение. В противном случае после применения к этому объекту оператора delete поведение программы непредсказуемо;
два объекта auto_ptr не должны получать во владение один и тот же объект. Очевидный способ допустить такую ошибку – присвоить одно значение двум объектам. Менее очевидный – с помощью операции get(). Вот пример:
auto_ptr string
pstr_auto( new string( "Brontosaurus" ) );
// ошибка: теперь оба указывают на один объект
// и оба являются его владельцами
auto_ptr string pstr_auto2( pstr_auto.get() );
*
Операция release() гарантирует, что несколько указателей не являются владельцами одного и того же объекта. release() не только возвращает адрес объекта, на который ссылается auto_ptr, но и передает владение им. Предыдущий фрагмент кода нужно переписать так:
// правильно: оба указывают на один объект,
// но pstr_auto больше не является его владельцем
auto_ptr string
pstr_auto2( pstr_auto.release() );
8.4.3. Динамическое создание и уничтожение массивов
Оператор new может выделить из хипа память для размещения массива. В этом случае после спецификатора типа в квадратных скобках указывается размер массива. Он может быть задан сколь угодно сложным выражением. new возвращает указатель на первый элемент массива. Например:
// создание единственного объекта типа int
// с начальным значением 1024
int *pi = new int( 1024 );
// создание массива из 1024 элементов
// элементы не инициализируются
int *pia = new int[ 1024 ];
// создание двумерного массива из 4x1024 элементов
int (*pia2)[ 1024 ] = new int[ 4 ][ 1024 ];
pi содержит адрес единственного элемента типа int, инициализированного значением 1024; pia – адрес первого элемента массива из 1024 элементов; pia2 – адрес начала массива, содержащего четыре массива по 1024 элемента, т.е. pia2 адресует 4096 элементов.