Зачем проверять на неравенство this в операторе присваивания?
От: Artifact  
Дата: 18.04.14 16:18
Оценка:
Разве кто-то в здравом уме станет присваивать что-то самому себе? И, если уж так вышло, не является ли это ошибкой? И не лучше ли тогда вместо
MyClass& operator=(const MyClass& other) {
    if(this != &other) {
         * * *
    }
}

писать
MyClass& operator=(const MyClass& other) {
    assert(this != &other)
    * * *
}
__________________________________
Не ври себе.
Re: Зачем проверять на неравенство this в операторе присваивания?
От: The Passenger Голландия  
Дата: 18.04.14 16:26
Оценка: 2 (2) +2
Здравствуйте, Artifact, Вы писали:

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

... и да — ассерт работает только в дебаге
Весь мир — Кремль, а люди в нем — агенты
Re: Зачем проверять на неравенство this в операторе присваивания?
От: bydlocoder  
Дата: 18.04.14 17:14
Оценка:
Здравствуйте, Artifact, Вы писали:

A>Разве кто-то в здравом уме станет присваивать что-то самому себе?



X a;
// много индусского кода...
const X& b = a;
// moarrrr!
a = b;



A>И, если уж так вышло, не является ли это ошибкой?

Разумеется, и по закону Мерфи выстрелит она именно в продакшене


X& operator=(const X& rhs){
    clear_me();
    X tmp(rhs);
    swap(&this, tmp); //BOOM!
    return *this;
}


Так что лучше уж проверить
Re: Зачем проверять на неравенство this в операторе присваивания?
От: Evgeny.Panasyuk Россия  
Дата: 18.04.14 21:03
Оценка: +1 -2
Здравствуйте, Artifact, Вы писали:

A>Разве кто-то в здравом уме станет присваивать что-то самому себе? И, если уж так вышло, не является ли это ошибкой? И не лучше ли тогда вместо

A>
MyClass& operator=(const MyClass& other) {
A>    if(this != &other) {
A>         * * *
A>    }
A>}

A>писать
A>
MyClass& operator=(const MyClass& other) {
A>    assert(this != &other)
A>    * * *
A>}


Это всего лишь традиция, причём не особо удачная. Я бы предпочёл второй вариант с assert'ом, то есть рассматривать самоприсваивание как ошибку, нарушение precondition. Да, assert работает не всегда — но precondition и не нужно всегда проверять.
Не особо разумно вставлять дорогую проверку, которая выполняется всегда, ради каких-то маргинальных случаев.

Вот, например, что говорит Александр Степанов по этому поводу: Efficient Programming with Components: Lecture 2 Part 2
Re: Зачем проверять на неравенство this в операторе присваивания?
От: __kot2  
Дата: 18.04.14 21:28
Оценка:
Здравствуйте, Artifact, Вы писали:
A>Разве кто-то в здравом уме станет присваивать что-то самому себе?
да конечно никто никогда такой фигней не мается
чаще бывает, что кто-то пишет цикл, где делает, например swap пар обьектов и все вроде бы хорошо работает, пока случайно по какой-то причине обьекты не свопадут и этот свап не упадет из-за такого ньюанса оператора присваивания. неудобно
Re[2]: Зачем проверять на неравенство this в операторе присваивания?
От: Evgeny.Panasyuk Россия  
Дата: 18.04.14 21:34
Оценка:
Здравствуйте, __kot2, Вы писали:

__>да конечно никто никогда такой фигней не мается

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

Опять же — это всего лишь convention: кто будет делать проверку — сам объект или хитровывернутый алгоритм.
Так как такая проверка требуется крайне редко, то я бы предпочёл второй вариант (+assert'ы если самоприсваивание может порушить инварианты).
Re[3]: Зачем проверять на неравенство this в операторе присваивания?
От: __kot2  
Дата: 18.04.14 23:05
Оценка: +1
Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>Опять же — это всего лишь convention: кто будет делать проверку — сам объект или хитровывернутый алгоритм.
EP>Так как такая проверка требуется крайне редко, то я бы предпочёл второй вариант (+assert'ы если самоприсваивание может порушить инварианты).
вообще, я в своем коде таких проверок не пишу, но, думаю, для библиотечного это уже стало стандартом и надо ему следовать
Re[4]: Зачем проверять на неравенство this в операторе присваивания?
От: Evgeny.Panasyuk Россия  
Дата: 18.04.14 23:12
Оценка:
Здравствуйте, __kot2, Вы писали:

__>вообще, я в своем коде таких проверок не пишу, но, думаю, для библиотечного это уже стало стандартом и надо ему следовать


Согласен — эта convention крайне популярна. Видимо этот поезд уже ушёл, к сожалению.
Re: Зачем проверять на неравенство this в операторе присваивания?
От: Юрий Жмеренецкий ICQ 380412032
Дата: 19.04.14 03:00
Оценка: 1 (1) +1
Здравствуйте, Artifact, Вы писали:

A>Разве кто-то в здравом уме станет присваивать что-то самому себе? И, если уж так вышло, не является ли это ошибкой? И не лучше ли тогда вместо

A>
MyClass& operator=(const MyClass& other) {
A>    if(this != &other) {
A>         * * *
A>    }
A>}

A>писать
A>
MyClass& operator=(const MyClass& other) {
A>    assert(this != &other)
A>    * * *
A>}


В подавляющем большинстве случаев опрератор присваивания можно реализовать с помощью метода copy-and-swap, который корректно работает без лишней проверки в случае присваивания "самому себе".
Re[2]: Зачем проверять на неравенство this в операторе присваивания?
От: Andrew S Россия http://alchemy-lab.com
Дата: 21.04.14 18:23
Оценка: +2
За такое надо ... даже не могу придумать что сделать. Ну, Саттера заставить перечитать 20 раз, что ли.

B>
B>X& operator=(const X& rhs){
B>    clear_me(); // Эвона как. А если сконструировать не получится???
B>    X tmp(rhs); 
B>    swap(&this, tmp); //BOOM! Причем на этапе компиляции. А если поправить ошибку - то получим горку бессмысленного кода.
B>                      // swap должен быть перегружен для X и не кидать исключения. Иначе получим рекурсию. А если перегружен - то не получим ошибку, за исключением выше.
B>    return *this;
B>}

B>


Просто посмотреть гвайд:

X & operator = (X rhs)
{
    using namespace std;
    swap(*this, rhs);
    return *this;
}



B>Так что лучше уж проверить


Лучше не писать овнокод.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[3]: Зачем проверять на неравенство this в операторе присваивания?
От: slava_phirsov Россия  
Дата: 22.04.14 13:29
Оценка: -1
Здравствуйте, Andrew S, Вы писали:


AS>Просто посмотреть гвайд:


AS>
AS>X & operator = (X rhs)
AS>{
AS>    using namespace std; // а вот за такое... да два-три раза...
AS>    swap(*this, rhs); // а оно будет работать в до-C++11 режиме, без move semantic? Чё-т неверится. Походу, обратится к operator=, не?
AS>    return *this;
AS>}
AS>
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[4]: Зачем проверять на неравенство this в операторе присваивания?
От: Evgeny.Panasyuk Россия  
Дата: 22.04.14 13:46
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

AS>>
AS>>X & operator = (X rhs)
AS>>{
AS>>    using namespace std; // а вот за такое... да два-три раза...
AS>>

ADL

AS>> swap(*this, rhs); // а оно будет работать в до-C++11 режиме, без move semantic? Чё-т неверится. Походу, обратится к operator=, не?

AS>>[/ccode]

AS>// swap должен быть перегружен для X и не кидать исключения. Иначе получим рекурсию. А если перегружен — то не получим ошибку, за исключением выше.

Re[5]: Зачем проверять на неравенство this в операторе присваивания?
От: slava_phirsov Россия  
Дата: 22.04.14 13:54
Оценка: -1 :)
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>

AS>>// swap должен быть перегружен для X и не кидать исключения. Иначе получим рекурсию. А если перегружен — то не получим ошибку, за исключением выше.



Теперь осталось только уточнить, а что же будет делать перегруженный swap? Насколько я могу понять, то же самое, что раньше делал копирующий operator= И какой смысл менять шило на мыло?
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[6]: Зачем проверять на неравенство this в операторе присваивания?
От: Evgeny.Panasyuk Россия  
Дата: 22.04.14 14:00
Оценка: :)
Здравствуйте, slava_phirsov, Вы писали:

_>Теперь осталось только уточнить, а что же будет делать перегруженный swap? Насколько я могу понять, то же самое, что раньше делал копирующий operator= И какой смысл менять шило на мыло?


Как думаешь, зачем std::vector'у свой swap и что он делает? Или ты спрашиваешь про идиому copy-and-swap в целом?
Re[3]: Зачем проверять на неравенство this в операторе присваивания?
От: bydlocoder  
Дата: 22.04.14 14:05
Оценка: +2
Здравствуйте, Andrew S, Вы писали:

AS>За такое надо ... даже не могу придумать что сделать. Ну, Саттера заставить перечитать 20 раз, что ли.


"Те не понял, защитник братьев меньших" (с) Jay and Silent Bob
Я не призываю так писать.
Вопрос ТС был в том, кто в здравом уме будет присваивать себе.

Я привел вполне жизненный юзкейс, а также пример, когда он приведет к очень-очень плохим последствиям

B>>
B>>X& operator=(const X& rhs){
B>>    clear_me(); // Эвона как. А если сконструировать не получится???
B>>


Спасибо, Капитан!

AS>Лучше не писать овнокод.

Это все хорошо, пока живешь в мире розовых пони, которые кушают радугу и какают бабочками.
Если возраст codebase около 20 лет, а размер — несколько сотен мегабайт, случай, когда исправляешь memleak, а на нем строится некая логика в соседней либе — это не страшный сон, а реальная жизнь
Re[7]: Зачем проверять на неравенство this в операторе присваивания?
От: slava_phirsov Россия  
Дата: 22.04.14 14:13
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:


EP>Как думаешь, зачем std::vector'у свой swap и что он делает? Или ты спрашиваешь про идиому copy-and-swap в целом?


Я думаю, что сразу же бежать за swap для перегрузки operator= — это перебор. Хотя, если цель разработчика в том, чтобы показать свою нереальную крутизну — то да, сгодится и swap.

Цитирую оригинал

Просто посмотреть гвайд:

X & operator = (X rhs)
{
using namespace std;
swap(*this, rhs);
return *this;
}


Ну, где здесь swap перегружен? В итоге получим то, что получим.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[4]: Зачем проверять на неравенство this в операторе присваивания?
От: slava_phirsov Россия  
Дата: 22.04.14 14:19
Оценка: :)
Здравствуйте, slava_phirsov, Вы писали:

_>Здравствуйте, Andrew S, Вы писали:



AS>>Просто посмотреть гвайд:


AS>>
AS>>X & operator = (X rhs)
AS>>{
AS>>    using namespace std; // а вот за такое... да два-три раза...
AS>>    swap(*this, rhs); // Без перегрузки перемещающего к-тора (или swap) оно, по ходу, и в C++11 уйдет в рекурсию
AS>>    return *this;
AS>>}
AS>>
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[8]: Зачем проверять на неравенство this в операторе присваивания?
От: Evgeny.Panasyuk Россия  
Дата: 22.04.14 14:23
Оценка:
Здравствуйте, slava_phirsov, Вы писали:

EP>>Как думаешь, зачем std::vector'у свой swap и что он делает? Или ты спрашиваешь про идиому copy-and-swap в целом?

_>Я думаю, что сразу же бежать за swap для перегрузки operator= — это перебор. Хотя, если цель разработчика в том, чтобы показать свою нереальную крутизну — то да, сгодится и swap.

Идиома copy-and-swap — самый простой способ получить exception safety, причём strong

_>Цитирую оригинал

_>

_>Просто посмотреть гвайд:

_>X & operator = (X rhs)
_>{
_> using namespace std;
_> swap(*this, rhs);
_> return *this;
_>}

_>Ну, где здесь swap перегружен? В итоге получим то, что получим.

Прочитай сообщение
Автор: Andrew S
Дата: 21.04.14
полностью:

AS>// swap должен быть перегружен для X и не кидать исключения. Иначе получим рекурсию. А если перегружен — то не получим ошибку, за исключением выше.

Re[9]: Зачем проверять на неравенство this в операторе присваивания?
От: slava_phirsov Россия  
Дата: 22.04.14 14:40
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

EP>Прочитай сообщение
Автор: Andrew S
Дата: 21.04.14
полностью:

AS>>// swap должен быть перегружен для X и не кидать исключения. Иначе получим рекурсию. А если перегружен — то не получим ошибку, за исключением выше.



Вот-вот в комментарии автор написал, что это сделать нужно, а добавить соответствующий код (ну хоть с бла-бла-бла вместо реального тела функции) — забыл. Что как бы намекает...
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re: Зачем проверять на неравенство this в операторе присваивания?
От: Mr.Delphist  
Дата: 23.04.14 09:10
Оценка:
Здравствуйте, Artifact, Вы писали:

A>Разве кто-то в здравом уме станет присваивать что-то самому себе? И, если уж так вышло, не является ли это ошибкой?


Задача:
В урне находится 5 синих шаров и 5 зелёных. Опускаем руку в урну и касаемся пальцем одного из шаров. Опускаем в ту же урну вторую руку и тоже касаемся пальцем одного из шаров. Какова вероятность, что пальцы обоих рук касаются одного и того же шара? Почему эта вероятность не может быть нулевой? Ответ обоснуйте. Вопрос со звёздочкой: зависит ли эта вероятность от цвета шаров?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.