Модераторы: Daevaorn

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Как не надо писать код 
:(
    Опции темы
ТарасАтавин
Дата 18.9.2013, 14:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  5.9.2013,  17:37 Найти цитируемый пост)
MyClass& MyClass::operator=(const MyClass &other)
{
   MyClass(other).swap(*this);
/*
   Можно написать так:
   MyClass tmp(other);
   tmp.swap(*this);
   но вариант выше короче (генерируемый код одинаков)
*/
}
Своп предполагает, что присваивание происходит сразу и слева на право, и наоборот, const запрещает всякое изменение правого операнда. Даже если эта пакость скомпилится, первая мысль при чтении такого безобразия будет или прямо противоположной, или, что опретор присваивания меняет оба операнда. А на, чтоб разобраться, уйдёт время. Убирать const - ещё хуже: оператор именно поменяет местами свои операнды, чего делать не должен.


Это сообщение отредактировал(а) ТарасАтавин - 18.9.2013, 14:37


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
Guinness
Дата 18.9.2013, 14:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 309
Регистрация: 21.6.2009
Где: Зеленоград

Репутация: нет
Всего: 10



ТарасАтавин, вообще-то, это классика как нужно писать оператор присваивания, чтобы делать его "безопасным для исключений"(тут с термином мог ошибиться, не помню как у Саттера там классификация идет). Более того, таким образом мы гарантируем, что и копирующий конструктор и оператор присваивания у нас делают одно и тоже.
А если конструкция не привычна для восприятия, то нужно привыкать.
PM MAIL   Вверх
ТарасАтавин
Дата 18.9.2013, 18:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(Guinness @  18.9.2013,  14:42 Найти цитируемый пост)
ТарасАтавин, вообще-то, это классика как нужно писать оператор присваивания, чтобы делать его "безопасным для исключений"
А как можно умудриться сделать опасный оператор присваивания? Кроме MyClass& MyClass::operator=(MyClass &other)
{
   MyClass(other).swap(*this);
}[/code], конечно. Кстати, оператор присваивания обязан возвращать ссылку на this, так что ваша "классика" страдает грубым нарушением стандарта.

Это сообщение отредактировал(а) ТарасАтавин - 18.9.2013, 18:58


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
mes
Дата 18.9.2013, 19:49 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


любитель
****


Профиль
Группа: Участник Клуба
Сообщений: 7954
Регистрация: 14.1.2006

Репутация: 144
Всего: 250



Цитата(ТарасАтавин @  18.9.2013,  13:36 Найти цитируемый пост)
const запрещает всякое изменение правого операнда
правый операнд это other ? больше ничего с конст не нахожу.. 
и где ктор его меняет  smile  smile 

Цитата(ТарасАтавин @  5.9.2013,  13:09 Найти цитируемый пост)
У меня 13 лет практического опыта

 smile не дай бог попасть кому-нибудь к врачу с таким же 13 летним опытом...

Добавлено через 2 минуты и 9 секунд
Цитата(ТарасАтавин @  18.9.2013,  17:56 Найти цитируемый пост)
 Кстати, оператор присваивания обязан возвращать ссылку на this, 

а как насчет того, чтоб читать между строк  ? 
эта строчка с возвращением this никакой роли не влияет, потом в форумных примерах на коленке может быть безболезнено упущена  smile

Добавлено через 6 минут и 49 секунд
 smile 
ТарасАтавин, был тут на форуме уже докторКтоТоТам, тоже себя в грудь бил и кричал громче всех.. 
еще и книжки писал.. Вы еще не пробовали ? что ж ценный опыт пропадает ... 




--------------------
PM MAIL WWW   Вверх
baldina
Дата 19.9.2013, 10:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(mes @  18.9.2013,  19:49 Найти цитируемый пост)
был тут на форуме уже докторКтоТоТам

немало ИТшных форумов, где он был заблокирован...  smile 
PM MAIL   Вверх
bsa
Дата 20.9.2013, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



ТарасАтавин, расскажи, что делает конструкция MyClass(*this)?
PM   Вверх
azesmcar
Дата 24.9.2013, 13:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(Guinness @  18.9.2013,  14:42 Найти цитируемый пост)
вообще-то, это классика как нужно писать оператор присваивания, чтобы делать его "безопасным для исключений"

вообще-то любая функция, которая при возникновении исключений гарантирует отсутствие утечки ресурсов уже сама по себе является exception safe, так-как соответствует базовому правилу безопасности исключений Абрахамса (раз уж вспомнили Сатера, то Сатер в своей книге цитировал именно его). А сохранение состояния программы при возникновении исключений является строгой гарантией, которую можно обеспечивать а можно и нет, зависит от программы.

PM   Вверх
azesmcar
Дата 24.9.2013, 16:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


uploading...
****


Профиль
Группа: Участник Клуба
Сообщений: 6291
Регистрация: 12.11.2004
Где: Армения

Репутация: 81
Всего: 211



Цитата(ТарасАтавин @  5.9.2013,  11:24 Найти цитируемый пост)
Нормально он себя поведёт, непроиниченный объект просто содержит мусор. 

Да, а что если это не тривиальный объект с двумя целочисленными типами а скажем что нибудь посложнее..ну например вот такой класс
Код

class X
{
public:
   X()
   {
      iptr = 0;
   }

   X(int v)
   {
      iptr = new int(v);
   }

   ~X()
   {
      delete iptr;
   }

   X& operator = (const X& p)
   {
      delete iptr;

      if (p.iptr != 0)
      {
         iptr = new int(*p.iptr);
      } else
      {
         iptr = 0;
      }

      return *this;
   }
private:
   int* iptr;
};

Что буде на 21-ой строке, если он содержит мусор?

Это сообщение отредактировал(а) azesmcar - 24.9.2013, 16:04
PM   Вверх
ТарасАтавин
Дата 7.10.2013, 18:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(mes @  18.9.2013,  19:49 Найти цитируемый пост)
и где ктор его меняет
swap.

Добавлено @ 18:28
Цитата(mes @  18.9.2013,  19:49 Найти цитируемый пост)
а как насчет того, чтоб читать между строк  ? 
Даже если return *this спрятано внутри swap, реализация оператора присваивания не содержит этой операции, а по стандарту должна.

Добавлено @ 18:31
Цитата(mes @  18.9.2013,  19:49 Найти цитируемый пост)
ТарасАтавин, был тут на форуме уже докторКтоТоТам, тоже себя в грудь бил и кричал громче всех.. 
еще и книжки писал.. Вы еще не пробовали ? что ж ценный опыт пропадает ... 
И это говорит человек, игнорирующий return *this. Ну ка как должен повести себя 
Код
class MyClass
 public:
  void operator = (MyClass &x);
...
 при 
Код
MyClass a, b, c;
...
a=b=c;
? По идее компилятор должен ругнуться, в то время как для всех встроенных типов это вполне валидная строка и 
Код
class MyClass
 public:
  MyClass &operator = (MyClass &x);
...
 сохраняет её валидность. То есть пропущенный return *this или вызовет лишний warning, что чревато пропуском уже серьёзной ошибки, или меняет интерфейс стандартного оператора, что как раз есть классика наглядных пособий как делать не надо.

Добавлено через 10 минут и 20 секунд
Цитата(bsa @  20.9.2013,  12:34 Найти цитируемый пост)
 расскажи, что делает конструкция MyClass(*this)? 
Копирует, да вот беда: анализ подобных мелочей занимает лишнее время, а по закону Мёрфи, гласящему что всё, что может быть понято не правильно, именно так и будет понято, кто нибудь обязательно его вообще не заметит.


Это сообщение отредактировал(а) ТарасАтавин - 7.10.2013, 18:34


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
ТарасАтавин
Дата 7.10.2013, 18:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(azesmcar @  24.9.2013,  16:04 Найти цитируемый пост)
Да, а что если это не тривиальный объект с двумя целочисленными типами а скажем что нибудь посложнее..ну например вот такой класс
А как на счёт объекта, декларация членов-данных которого занимают более пяти экранов? malloc от этого не зависит, а первое же присваивание мусор затрёт. А объект, знающий, что он - узел дерева с динамическим массивом потомков и при этом ещё одновременно содержащий несколько динамических массивов объектов других классов, чьи экземпляры не знают, где они валяются? в указатель отдельным присваиванием пишется NULL, потом присваивание всего объекта, затирающее остальной мусор. Только это не удобно. А удобно и уместно вызывать конструктор оператором new.

Это сообщение отредактировал(а) ТарасАтавин - 7.10.2013, 18:48


--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
bsa
Дата 9.10.2013, 10:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



ТарасАтавин, ты что к мелочам цепляешься? Тебе концепцию показывают. Естественно, что в нормальном коде должен быть и return *this. Он в данном случае не он главное. Главное, каким образом реализуется основная функциональность.

Цитата(ТарасАтавин @  7.10.2013,  19:26 Найти цитируемый пост)
Копирует, да вот беда: анализ подобных мелочей занимает лишнее время, а по закону Мёрфи, гласящему что всё, что может быть понято не правильно, именно так и будет понято, кто нибудь обязательно его вообще не заметит.
Что и куда копирует?

Добавлено через 9 минут и 45 секунд
Цитата(ТарасАтавин @  7.10.2013,  19:46 Найти цитируемый пост)
А как на счёт объекта, декларация членов-данных которого занимают более пяти экранов?
Программиста надо уволить с записью в трудовой о непригодности к профессии.

Цитата(ТарасАтавин @  7.10.2013,  19:46 Найти цитируемый пост)
malloc от этого не зависит, а первое же присваивание мусор затрёт.
А кто проинициализировал присваиваемый объект? Что будет, если будет вызван деструктор изначального объекта?

Цитата(ТарасАтавин @  7.10.2013,  19:46 Найти цитируемый пост)
А объект, знающий, что он - узел дерева с динамическим массивом потомков и при этом ещё одновременно содержащий несколько динамических массивов объектов других классов, чьи экземпляры не знают, где они валяются?
Объекты не думают. Они являются. И есть стандартное правило - освобождением ресурсов занимается тот, кто их выделяет. Исключение (условное) - умные указатели.

Цитата(ТарасАтавин @  7.10.2013,  19:46 Найти цитируемый пост)
в указатель отдельным присваиванием пишется NULL, потом присваивание всего объекта, затирающее остальной мусор. Только это не удобно. А удобно и уместно вызывать конструктор оператором new.
Вот и объясни, зачем мучаться с malloc/new()/деструктор/free, когда можно использовать new/delete? Более того, можно использовать умные указатели, и в этом случае тебе достаточно будет сделать только new, а все остальное ляжет на плечи указателя.

PM   Вверх
ТарасАтавин
Дата 9.10.2013, 12:34 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 370
Регистрация: 26.8.2013

Репутация: нет
Всего: нет



Цитата(bsa @  9.10.2013,  10:59 Найти цитируемый пост)
ты что к мелочам цепляешься? Тебе концепцию показывают. Естественно, что в нормальном коде должен быть и return *this. Он в данном случае не он главное. Главное, каким образом реализуется основная функциональность.
Именно с таким подходом его и не оказывается в коде релиза. И не только его, но и 
Код
int rnd ()
{
 return 14; /*Проверено: 14 - стопроцентно случайное число*/
}
, наоборот, оказывается в коде.

Добавлено через 2 минуты и 36 секунд
Цитата(bsa @  9.10.2013,  10:59 Найти цитируемый пост)
Что и куда копирует?
Какая разница? Речь о том, что код читается, как 
Код
swap(*this, Parametr);
, то есть обмен параметра местами с мусором, а не о том, что именно это он и означает.



--------------------
Не так всё плохо, как оно есть на самом деле.
PM MAIL   Вверх
baldina
Дата 9.10.2013, 12:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 32
Всего: 101



Цитата(bsa @  9.10.2013,  10:59 Найти цитируемый пост)
cтандартное правило - освобождением ресурсов занимается тот, кто их выделяет

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

Добавлено через 1 минуту
Цитата(ТарасАтавин @  9.10.2013,  12:34 Найти цитируемый пост)
Именно с таким подходом его и не оказывается в коде релиза.

это уже мозгоклюйство. ведь все всё поняли. 
PM MAIL   Вверх
bsa
Дата 10.10.2013, 12:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Модератор
Сообщений: 9185
Регистрация: 6.4.2006
Где: Москва, Россия

Репутация: 63
Всего: 196



Цитата(ТарасАтавин @  9.10.2013,  13:34 Найти цитируемый пост)
то есть обмен параметра местами с мусором, а не о том, что именно это он и означает.
 smile 
Где ты мусор тут нашел? Оператор присваивания ВСЕГДА оперирует с инициализированными объектами. Если какой-то негодяй не инициализирует объекты в конструкторе, то это его проблемы. Дальнейшие рассуждения по поводу качества кода с ним можно не продолжать.
PM   Вверх
Lukkoye
Дата 4.1.2014, 01:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 86
Регистрация: 23.3.2013

Репутация: 1
Всего: 1



Цитата(bsa @  19.3.2012,  13:18 Найти цитируемый пост)
Самый быстрый доступ к элементам в векторе. Самое быстрое удаление/вставка в середину в списке.


Существует миф, который заслуживает того, что бы его разоблачили.

Действительно: вставка у листа быстрая. Однако, реализация со стандартным аллокатором задействует оператор new. 
Который черезвычайно медленный. 

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

Таким образом, если вы используете стандартный аллокатор листа, который идет в с ним по дефолту, то по скорости работы на прикладных задачах он редко когда выигрывает у вектора. И никогда не выигрывает, если количество элементов - не велико.

Использовать его ради достижения перфоманса имеет смысл, если вы используете свои аллокаторы с уже заранее зарезервированной памятью. И не имеете потерь на её выделение оператором new


PM MAIL   Вверх
Google
  Дата 18.11.2019, 20:22 (ссылка)  





  Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++:Общие вопросы"
Earnest Daevaorn

Добро пожаловать!

  • Черновик стандарта C++ (за октябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика(4.4мб).
  • Черновик стандарта C (за сентябрь 2005) можно скачать с этого сайта. Прямая ссылка на файл черновика (3.4мб).
  • Прежде чем задать вопрос, прочтите это и/или это!
  • Здесь хранится весь мировой запас ссылок на документы, связанные с C++ :)
  • Не брезгуйте пользоваться тегами [code=cpp][/code].
  • Пожалуйста, не просите написать за вас программы в этом разделе - для этого существует "Центр Помощи".
  • C++ FAQ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Earnest Daevaorn

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 2.8331 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.