Интересная тема: This-pointing Classes
От: LaptevVV Россия  
Дата: 26.07.25 05:38
Оценка: 6 (3)
https://biowpn.github.io/bioweapon/2025/07/13/this-pointing-classes.html
Вроде как move становится простым как "два байта" переслать.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Интересная тема: This-pointing Classes
От: T4r4sB Россия  
Дата: 26.07.25 08:19
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Вроде как move становится простым как "два байта" переслать.


Наоборот, move усложняется, потому что надо не просто скопировать содержимое, а поправить "указатели на себя".
Именно из-за таких классов move сделан таким сложным, потому что иначе его можно было бы реализовать тупо побитовой копией (а оригинал принудительно делать placement new() на конструктор-по-умолчанию), а вектор можно было бы реаллоцировать полным аналогом сишного реаллок.
И что характерно, именно самоссылающиеся классы как раз не используют в векторах и там где нужен move. Так что получается что кресотмув — переусложнённый ненужный кусок говна.
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[2]: Интересная тема: This-pointing Classes
От: LaptevVV Россия  
Дата: 26.07.25 09:11
Оценка:
LVV>>Вроде как move становится простым как "два байта" переслать.
TB>Наоборот, move усложняется, потому что надо не просто скопировать содержимое, а поправить "указатели на себя".
Ну, оно и хорошо — народ прочитает и знать будет.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[2]: Интересная тема: This-pointing Classes
От: rg45 СССР  
Дата: 26.07.25 10:44
Оценка:
Здравствуйте, T4r4sB, Вы писали:


TB>Наоборот, move усложняется, потому что надо не просто скопировать содержимое, а поправить "указатели на себя".


Он усложняется уже хотя бы тем, что его нужно написать, в том или ином виде. Тогда как в подавляющем большинстве случаев, для несамореференсных классов, с этим спокойно справляется сам компилятор.

TB>Так что получается что кресотмув — переусложнённый ненужный кусок говна.


+1
--
Справедливость выше закона. А человечность выше справедливости.
Re: Интересная тема: This-pointing Classes
От: Великий Мессия google
Дата: 26.07.25 11:00
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>https://biowpn.github.io/bioweapon/2025/07/13/this-pointing-classes.html

LVV>Вроде как move становится простым как "два байта" переслать.

вроде как =delete это не решается
копи елижин который появился начиная с С++17
может проходить даже когда стоит запрет на операции копирования и перемещения класса

может конечно бага компилятора, хз
у меня были случая когда с этим сталкивался, под рукой примера нет
правда я уже больше десятка раз обновил и msvc и clang

но Константин Владимиров у себя в уроках тоже показывал похожие примеры
там только наоборот
имплементация есть, но она не вызывается у класа

в целом это было известно
видимо автор по ссылкам наткнулся на этом спустя 8 лет когда вышел стандарт С++17
Re[2]: Интересная тема: This-pointing Classes
От: T4r4sB Россия  
Дата: 26.07.25 12:17
Оценка:
Здравствуйте, Великий Мессия, Вы писали:

ВМ>вроде как =delete это не решается

ВМ>копи елижин который появился начиная с С++17
ВМ>может проходить даже когда стоит запрет на операции копирования и перемещения класса

Если ты про RVO/NRVO, то на нём это никак не должно сказываться, потому что адрес объекта не меняется. Так что даже при запрете на мув, такой код должен отлично работать:
Unmovable foo() {
  Unmovable local(1, 2);
  local.mutate();
  return local;
}
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Re[3]: Интересная тема: This-pointing Classes
От: rg45 СССР  
Дата: 26.07.25 12:49
Оценка: +1
Здравствуйте, T4r4sB, Вы писали:

TB>Если ты про RVO/NRVO, то на нём это никак не должно сказываться, потому что адрес объекта не меняется. Так что даже при запрете на мув, такой код должен отлично работать:

TB>
TB>Unmovable foo() {
TB>  Unmovable local(1, 2);
TB>  local.mutate();
TB>  return local;
TB>}
TB>


Не должен. Это случай NRVO — перемещения МОЖЕТ не случиться, но оно должно быть разрешено.

А вот RVO обязано работать, даже при запрещённом перемещении:

Unmovable foo() {
  return Unmovable(1, 2);
}
--
Справедливость выше закона. А человечность выше справедливости.
Отредактировано 26.07.2025 12:51 rg45 . Предыдущая версия .
Re[4]: Интересная тема: This-pointing Classes
От: T4r4sB Россия  
Дата: 26.07.25 13:02
Оценка:
Здравствуйте, rg45, Вы писали:


R>Не должен. Это случай NRVO — перемещения МОЖЕТ не случиться, но оно должно быть разрешено.


Да, обидно. Причём я даже не знаю какой актуальный компилятор не будет делать NRVO
Нет такой подлости и мерзости, на которую бы не пошёл gcc ради бессмысленных 5% скорости в никому не нужном синтетическом тесте
Отредактировано 26.07.2025 13:03 T4r4sB . Предыдущая версия .
Re[5]: Интересная тема: This-pointing Classes
От: rg45 СССР  
Дата: 26.07.25 13:05
Оценка:
Здравствуйте, T4r4sB, Вы писали:

TB>Да, обидно

TB>https://rextester.com/QDNM13581

Ну, с другой стороны, никто ведь ничего другого и не обещал. Mandatory (guaranteed) copy/move elision обещано только для RVO. А NRVO как было, так и осталось оптимизацией — т.е. на усмотрение компилятора.
--
Справедливость выше закона. А человечность выше справедливости.
Re: Интересная тема: This-pointing Classes
От: vopl Россия  
Дата: 26.07.25 13:06
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>https://biowpn.github.io/bioweapon/2025/07/13/this-pointing-classes.html

LVV>Вроде как move становится простым как "два байта" переслать.

Профессор, при всем уважении, Вам надо как то более качественно изучать материалы которые Вы приносите. Там поинт совсем в другом.
Re[2]: Интересная тема: This-pointing Classes
От: LaptevVV Россия  
Дата: 26.07.25 13:33
Оценка: +1
LVV>>https://biowpn.github.io/bioweapon/2025/07/13/this-pointing-classes.html
LVV>>Вроде как move становится простым как "два байта" переслать.
V>Профессор, при всем уважении, Вам надо как то более качественно изучать материалы которые Вы приносите. Там поинт совсем в другом.
Ну, с этим разобрались...
Но вообще говоря — чего только народу в голову не приходит — извращения всякие...
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[3]: Интересная тема: This-pointing Classes
От: rg45 СССР  
Дата: 26.07.25 14:37
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>Но вообще говоря — чего только народу в голову не приходит — извращения всякие...


Я не рискну говорить за всех, но, из моего личного опыта, во всех случаях, когда возникали вот такие самореференсные классы — это всегда был говнодизайн. И всегда получалось перепроектировать.
--
Справедливость выше закона. А человечность выше справедливости.
Re[4]: Интересная тема: This-pointing Classes
От: sergii.p  
Дата: 28.07.25 11:54
Оценка: +1
Здравствуйте, rg45, Вы писали:

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


тот же circular_buffer из примера. Хранили бы size_t head_ вместо T* head_. И вопрос странного перемещения решается сам собой.
Re: the only safe way is to ban move
От: sergii.p  
Дата: 28.07.25 11:55
Оценка: :)
Здравствуйте, LaptevVV, Вы писали:

цитата из статьи. Немного вырвал из контекста, но получается смешно
Re: Интересная тема: This-pointing Classes
От: B0FEE664  
Дата: 28.07.25 13:38
Оценка: +1
Здравствуйте, LaptevVV, Вы писали:

LVV>https://biowpn.github.io/bioweapon/2025/07/13/this-pointing-classes.html

LVV>Вроде как move становится простым как "два байта" переслать.

Судя по прочитанному это писал новичок в С++.
Жаль, что причина копирования this в поле класса не названа. Как по мне, любая попытка иметь две копии одного и того же данного — это путь к ошибке. Поэтому, в частности, написание кэша — сложная задача.

Что же по коду, то вот этот класс
class Widget {
    std::function<void()> foo_fn_;

  public:
    void foo1();
    void foo2();

    Widget() {
        foo_fn_ = [&]() { foo1(); };
        // or
        foo_fn_ = [this]() { foo2(); };
    }

    void foo() {
        foo_fn_();
    }
};

следует переписать так, чтобы было понятно, зачем нужен foo_fn_.

Если foo_fn_ — это callback, который отдают наружу, то:
class Widget 
{
  public:
    void foo1();
    void foo2();
    void foo() 
    {
        foo_fn_();
    }
    std::function<void()> GetCallback_foo2()
    {
      return foo_fn_;
    }
  private:
    Widget(const Widget&) = delete;
    Widget(Widget&&) = delete;
    auto operator=(const Widget&) = delete;
    auto operator=(Widget&&) = delete;
  private:  
    std::function<void()> foo_fn_ = [this]() { foo2(); };
};

Иногда в таком случае можно завернуть std::function<void()> в std::shared_ptr, если функтор выходит "тяжёлым".

Если же предназначение foo_fn_ — вычислить при инициализации, какой из методов вызывать при вызове foo(), то std::function вообще излишен:
class Widget
{
  public:
    void Up(){};
    void Down(){};
    void foo()
    {
        (this->*foo_fn_)();
    }

    Widget(int x)
      : foo_fn_(x < 0 ? &Widget::Down : &Widget::Up)
    {
    }
  private:
    void(Widget::*foo_fn_)();
};
И каждый день — без права на ошибку...
Re: Интересная тема: This-pointing Classes
От: Кодт Россия  
Дата: 30.07.25 15:10
Оценка: 17 (1)
Здравствуйте, LaptevVV, Вы писали:

LVV>https://biowpn.github.io/bioweapon/2025/07/13/this-pointing-classes.html


(Это называется "создать себе трудности и героически их превозмогать").

Нужно понимать, что все на свете объекты бывают трёх видов
— copyable (значение-подобные) — поведение системы не зависит от количества копий
— moveable — поведение не зависит от адреса (но копировать нельзя)
— неподвижные — идентичность определяется адресом

И, хотя контракт "неподвижные" реализовать проще всего, но контракт "значение-подобные" востребован слишком часто, чтобы компилятор дефолтился именно к нему.

Почему объект становится неподвижным — тут могут быть самые разные причины. Ссылки внутрь себя — лишь одни из них.
Другая причина — это внешние ссылки, например.
Когда объект (или его агрегат) принадлежит не только непосредственному владельцу, но и какому-нибудь реестру.
class Foo {
public:
  Foo() { .....; ::Register(this); }
  ~Foo() { ::Unregister(this); ..... }
  .....
};

Или когда объекты образуют граф ссылок друг на друга.

Те же виджеты в статье. Виджет — это то, чем владеет движок графического интерфейса. Мы создали объект и движку препоручили.

======

В некоторых случаях можно руками написать — как правильно копировать и/или переносить содержимое с одного места на другое.
Понятное дело, что эти "некоторые" случаи не обобщаются, каждый раз будет разный код.

Альтернатива — это вообще избавиться от необходимости перемещать содержимое.
shared_ptr и unique_ptr (и голые указатели с такой же семантикой, только вручную) превращают объект-фасад в копируемый, а объект-реализацию оставляют неподвижной.
Хотя всё равно копирование содержимого остаётся нетривиальным. Да ещё вылезают кольцевые зависимости.
Перекуём баги на фичи!
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.