Re: Оператор = для классов
От: Kirikaza Россия kirikaza.ru
Дата: 05.01.10 10:22
Оценка: 20 (2) +1
Здравствуйте, sanx.

Не сочтите за RTFM, но Мейерс С. Эффективное использование С++. 50(55) советов... (и бумажный, и e-лектронный вариант найти несложно; правда, необходимо отличать от второй книги автора Наиболее эффективное использование С++. 35 советов...). Имеется отдельная глава "Конструкторы, деструкторы и операторы присваивания", букаф немного. Думаю, в этой книге ответы найти быстрее и проще, чем на форуме; кроме того, там есть ответы на вопросы, которые могли и не придти в голову.
Re: Оператор = для классов
От: jazzer Россия Skype: enerjazzer
Дата: 05.01.10 07:47
Оценка: 3 (2)
Здравствуйте, sanx, Вы писали:

S>Не понимаю, почему просто не разрушать объект, вызывая его деструктор, и после вызывать конструктор копирования. Зачем нужно переопределять оператор "="? Понимаю еще "=+" и подобные. Но просто "=" — это же по сути отказ от старого объекта? Тем более что разумно автоматически возвращать сам этот объект в операторе "=", а с этим компилятор должен справиться без проблем. То есть 1) Разрушаем старый объект, 2) Вызываем нужный конструктор копирования, 3) Если нужно, возвращаем новый объект (если у нас a = b = c). Почему же тогда не так?


потому что в общем случае убить и создать дороже, чем скопировать.
Например, у тебя уже выделена память — и что, ее грохать и выделять по новой?
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[3]: Оператор = для классов
От: Кодт Россия  
Дата: 06.01.10 00:08
Оценка: +1
Здравствуйте, jazzer, Вы писали:

J>Я так понимаю, sanx имел в виду, чтоб это делалось самим компилятором по умолчанию (который "почти всегда" знает про все эти пляски) и оператора присваивания вообще не было в языке в принципе.


Доводы те же самые. Мысленно представь, что X::operator= был создан компилятором, и создан именно так: dtor-cctor.
После чего устраиваем провокацию и получаем кучу проблем на ровном месте.

В роли провокации выступают
— срезка, я уже показал как
— бросок исключения в cctor
Причём, если исключение возникает в операторе присваивания — мы можем получить несогласованное состояние объекта (а можем и логически согласованное), но хотя бы на самом примитивном уровне оно останется определённым. А после исключения из конструктора — состояние не просто несогласованное, а его нет как такового.
Перекуём баги на фичи!
Оператор = для классов
От: sanx  
Дата: 05.01.10 07:42
Оценка:
Не понимаю, почему просто не разрушать объект, вызывая его деструктор, и после вызывать конструктор копирования. Зачем нужно переопределять оператор "="? Понимаю еще "=+" и подобные. Но просто "=" — это же по сути отказ от старого объекта? Тем более что разумно автоматически возвращать сам этот объект в операторе "=", а с этим компилятор должен справиться без проблем. То есть 1) Разрушаем старый объект, 2) Вызываем нужный конструктор копирования, 3) Если нужно, возвращаем новый объект (если у нас a = b = c). Почему же тогда не так?
Re[2]: Оператор = для классов
От: sanx  
Дата: 05.01.10 07:56
Оценка:
Здравствуйте, jazzer, Вы писали:

J>потому что в общем случае убить и создать дороже, чем скопировать.

J>Например, у тебя уже выделена память — и что, ее грохать и выделять по новой?

Действительно. Как то не подумал. Да и еще вспомнил, о возможности просто хранить ссылку на тот же объект, и копировать только если будет изменение.
Re: Оператор = для классов
От: Кодт Россия  
Дата: 05.01.10 22:27
Оценка:
Здравствуйте, sanx, Вы писали:

S>Не понимаю, почему просто не разрушать объект, вызывая его деструктор, и после вызывать конструктор копирования.


Потому что это ведёт к неопределённому поведению, в общем случае.

struct X
{
  virtual ~X() {}
  virtual string whoami() cons { return "X"; }
  string a;

  X& operator = (X const& src) { this->~X(); new(this)X(src); return *this; }  
};

struct Y : X
{
  virtual ~Y() {} // или определено компилятором, не важно
  virtual string whoami() const { return "Y"; }
  string b;
};

int main()
{
  X x;
  x.a = "alfa";

  Y y;
  y.a = "beta";
  y.b = "gamma";

  y = x; // срезка: частичное присваивание

                      // честное присваивание   dtor-cctor
  cout << y.a;        // beta                   beta
  cout << y.whoami(); // Y                      X  wtf?!
  cout << y.b;        // gamma                  access violation
Перекуём баги на фичи!
Re[2]: Оператор = для классов
От: jazzer Россия Skype: enerjazzer
Дата: 06.01.10 00:00
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Здравствуйте, sanx, Вы писали:


S>>Не понимаю, почему просто не разрушать объект, вызывая его деструктор, и после вызывать конструктор копирования.


К>Потому что это ведёт к неопределённому поведению, в общем случае.


Я так понимаю, sanx имел в виду, чтоб это делалось самим компилятором по умолчанию (который "почти всегда" знает про все эти пляски) и оператора присваивания вообще не было в языке в принципе.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
Re[4]: Оператор = для классов
От: jazzer Россия Skype: enerjazzer
Дата: 06.01.10 01:42
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Причём, если исключение возникает в операторе присваивания — мы можем получить несогласованное состояние объекта (а можем и логически согласованное), но хотя бы на самом примитивном уровне оно останется определённым. А после исключения из конструктора — состояние не просто несогласованное, а его нет как такового.


Да, ты прав, исключение из конструктора убивает всю идею на корню.
jazzer (Skype: enerjazzer) Ночная тема для RSDN
Автор: jazzer
Дата: 26.11.09

You will always get what you always got
  If you always do  what you always did
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.