@ larsmans уже ответили на ваш точный вопрос, так что я действительно отступлю: Это какой-то дерьмовый код!
Проблема здесь в три раза:
- Вы только что продублировали код конструктора копирования (несколько)
strcpy
может быть лучше заменено на strncpy
, что делает некоторую связанную проверку
- Это не исключение безопасно
1) и 2) более стилистичны, чем что-либо еще, но 3) вызывает большую обеспокоенность
РЕДАКТИРОВАТЬ: , как указал @Jerry Coffin, это не защищает от самостоятельного назначения. То есть, если sobj
и _string
указывают на один и тот же массив символов, у вас большие проблемы. Простое решение в конце этого поста также охватывает эту ситуацию.
Не исключение безопасно
Давайте посмотрим на часть кода, а именно на else
часть:
_size = strlen( sobj );
delete[] _string;
_string = new char[ _size + 1 ];
strcpy( _string, sobj );
Что произойдет, если по какой-то причине new
бросит?
_size
имеет значение новой строки
_string
указывает на старый указатель ... который был освобожден
Поэтому не только объект остается в непригодном для использования состоянии (половина его данных от нового объекта, половина от старого), но он даже не может быть уничтожен (если деструктор не утекает ...?)
Добавление исключений безопасности, трудный путь
_size = strlen( sobj );
delete[] _string;
try {
_string = new char[ _size + 1 ];
} catch(...) {
_size = 0; _string = 0;
throw;
}
strcpy( _string, sobj );
Хорошо, это действительно практический результат, но он дает нам Базовую гарантию исключений : нет функциональной гарантии, но гарантия, что код технически корректен (без сбоев, без утечек).
Добавление безопасности исключений, простой способ: идиома Копировать-и-Поменять
Найти более полное описание можно по адресу: Что такое идиома копирования и обмена?
void swap(String& lhs, String& rhs) {
using std::swap;
swap(lhs._size, rhs._size);
swap(lhs._string, rhs._string);
}
String& String::operator=(String other) { // pass-by-value
swap(*this, other);
return *this;
}
Как это работает?
- мы повторно используем конструктор копии для фактической копии
- мы используем функцию обмена для обмена значениями
- мы повторно используем деструктор для очистки
И это даже лучше, чем в предыдущей версии, так как теперь у нас есть Сильная гарантия исключения : она транзакционная, поэтому, если она терпит неудачу, назначенная нам строка остается неизменной (как будто ничего не произошло) .
Подробнее о гарантиях исключений .
Я немного испугался, что учебник C ++ будет продвигать такой сомнительный код, скажите, пожалуйста, что это пример того, чего не следует делать: /