Скопируйте конструктора и = перегрузка оператора в C++: действительно ли общая функция возможна?

Где я работаю, мы использовали http://www.clickatell.com для отсылки SMS - это похоже на свои приблизительно 6 или 7 центов за сообщение. Они просто берут http запросы POST для отсылки сообщения. Я не знаю, будете ли Вы в состоянии найти какие-либо хорошие свободные шлюзы. Мы раньше посылали электронные письма, но нашли, что они были ненадежны.

81
задан sbi 6 November 2010 в 08:10
поделиться

3 ответа

Да. Есть два распространенных варианта. Один из них, который обычно не рекомендуется, заключается в явном вызове operator = из конструктора копирования:

MyClass(const MyClass& other)
{
    operator=(other);
}

Однако предоставление хорошего operator = является проблемой, когда дело доходит до работы с старое состояние и проблемы, возникающие при самостоятельном назначении. Кроме того, все элементы и базы инициализируются по умолчанию первыми, даже если они должны быть назначены из other . Это может быть даже не для всех членов и баз, и даже там, где это допустимо, оно семантически избыточно и может быть практически дорогостоящим.

Все более популярным решением является реализация operator = с использованием конструктора копирования и метод обмена.

MyClass& operator=(const MyClass& other)
{
    MyClass tmp(other);
    swap(tmp);
    return *this;
}

или даже:

MyClass& operator=(MyClass other)
{
    swap(other);
    return *this;
}

Функцию подкачки обычно легко написать, поскольку она просто меняет местами владение внутренними компонентами и не требует очистки существующего состояния или выделения новых ресурсов.

Преимущества копирования и подкачки идиома состоит в том, что это автоматически безопасное самоназначение и - при условии, что операция подкачки не вызывает выброса - также строго безопасна в отношении исключений.

Чтобы быть строго безопасным в отношении исключений, «рукописный» оператор присваивания обычно должен выделять копию новых ресурсов перед тем, как освободить старые ресурсы правопреемника, так что в случае возникновения исключения при распределении новых ресурсов старое состояние все еще может быть возвращено. Все это бесплатно с копированием и заменой, но, как правило, более сложное и, следовательно, подверженное ошибкам, выполнение с нуля.

Единственное, о чем следует быть осторожным, - это убедиться, что метод подкачки является истинным свопом, а не методом по умолчанию std :: swap , который использует сам конструктор копирования и оператор присваивания.

Обычно используется поэлементная своп . std :: swap работает, и для всех базовых типов и типов указателей гарантируется отсутствие выброса. Большинство интеллектуальных указателей также можно заменить с гарантией отсутствия выброса.

114
ответ дан 24 November 2019 в 09:40
поделиться

Конструктор копирования выполняет первоначальную инициализацию объектов, которые раньше были необработанной памятью. Оператор присваивания OTOH заменяет существующие значения новыми. Чаще, чем никогда, это связано с отказом от старых ресурсов (например, памяти) и выделением новых.

Если между ними есть сходство, так это то, что оператор присваивания выполняет уничтожение и копирование. Некоторые разработчики фактически реализовывали назначение путем уничтожения на месте с последующим копированием размещения. Однако это очень плохая идея. (Что, если это оператор присваивания базового класса, который вызывается во время присваивания производного класса?)

Что обычно считается канонической идиомой в наши дни - использовать swap , как предложил Чарльз:

MyClass& operator=(MyClass other)
{
    swap(other);
    return *this;
}

Здесь используется копирующая конструкция (обратите внимание, что копируется other ) и разрушение (она разрушается в конце функции) - и она также использует их в правильном порядке: построение (может завершиться ошибкой ) до разрушения (не должен потерпеть неудачу).

13
ответ дан 24 November 2019 в 09:40
поделиться

Возможно, вам потребуется просмотреть статью MSDN Чарльза Петцольда Визуализация текста по пути с WPF ( архивированная версия ).

wavy text

Я нашел эту статью очень полезной, и он также предоставляет образец, где он использует анимацию.

-121--3762839-

В какой-то момент время работы браузера истекает, и загрузка страницы прекращается. Если вы хотите проверить, откройте командную строку и запустите код там. Сценарий должен выполняться бесконечно долго.

-121--1918186-

Что-то беспокоит меня:

MyClass& operator=(const MyClass& other)
{
    MyClass tmp(other);
    swap(tmp);
    return *this;
}

Во-первых, чтение слова «поменяться», когда мой разум думает «копировать», раздражает мой здравый смысл. Кроме того, я ставлю под сомнение цель этого причудливого трюка. Да, любые исключения при построении новых (скопированных) ресурсов должны происходить до свопа, что кажется безопасным способом убедиться, что все новые данные заполнены, прежде чем перевести их в оперативный режим.

Это нормально. Так что насчет исключений, которые случаются после свопа? (когда старые ресурсы уничтожаются, когда временный объект выходит из области действия) С точки зрения пользователя назначения, операция потерпела неудачу, за исключением того, что не была выполнена. Это имеет огромный побочный эффект: копия действительно произошла. Не удалось очистить только некоторые ресурсы. Состояние целевого объекта было изменено, даже если операция, по-видимому, не удалась извне.

Поэтому я предлагаю вместо «свопа» сделать более естественную «передачу»:

MyClass& operator=(const MyClass& other)
{
    MyClass tmp(other);
    transfer(tmp);
    return *this;
}

Еще есть строительство временного объекта, но следующим немедленным действием является освобождение всех текущих ресурсов пункта назначения перед перемещением (и, таким образом, они не будут дважды освобождены) ресурсов источника к нему.

Вместо {construct, move, destruct} я предлагаю {construct, destruct, move}. Этот шаг, который является наиболее опасным действием, является последним после того, как все остальное было урегулировано.

Да, сбой разрушения является проблемой в любой схеме. Данные либо повреждены (скопированы, когда вы не думали, что это так), либо потеряны (освобождены, когда вы не думали, что это так). Потерянный лучше, чем испорченный. Нет данных лучше, чем неверные данные.

Передача вместо замены. В любом случае, это мое предложение.

-4
ответ дан 24 November 2019 в 09:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: