LINUX.ORG.RU

Хвалёные смарт-поинтеры.

 


0

5

Всем привет!

Сегодня в мире т.н. «modern C++» принято нахваливать смарт-поинтеры. Дескать, это такая крутая технология, которая решает множество проблем. Как это всегда получалось, решение одних проблем порождало решение других проблем. Какие проблемы порождают смарт-поинтеры? Рассмотрим код, который валиден и прекрасно собирается:

struct B {
  virtual B* clone() = 0;
};

struct D : B {
  virtual D* clone() = 0;
};

struct impl : D {
  D* clone() override
  {
    return new impl;
  }
};

int main()
{
  auto b = new impl;
  b->clone();
}

Но стоит только превратить указатели в std::unique_ptr, как всё перестаёт собираться. И вот это уже вызывает смех. Ведь если ув. эксперты, уполномоченные принимать решения в части изменения стандарта, ввели смарт-поинтеры в язык, громогласно заявив при этом, что хватит писать на «голых» указателях, т.к. в современном C++ уже всё на смарт-поинтерах, то почему же тогда с этими хвалёными стандартными смарт-поинтерами ломается ковариантность? :-) C++ как он есть.

А какие вы знаете проблемы со смарт-поинтерами в современном C++?

Ответ на: комментарий от Softwayer

А как иначе то? :-) Хотя как иначе - не использовать смарт-поинтеры повсеместно, наверное так :-)

azelipupenko
() автор топика

хватит писать на «голых» указателях, т.к. в современном C++ уже всё на смарт-поинтерах

Это просто такой маркетинговый призыв к людям, которые давно пишут на С++, посмотреть в сторону смартпоинтеров.
Никакой «мудрый совет» в жизни нельзя возводить в абсолют.
И никто не говорил, что надо убрать обычные указатели из языка, а соответственно подразумевается что они нужны где-то, а это значит что смартпоинтеры != и не заменяют обычные указатели, а просто являются более лучшими для решения некоторых задач, а там где нужно — там использовать обычные указатели, те же смартпоинтеры внутри себя используют обычные указатели.

Bad_ptr ★★★★★
()

громогласно заявив при этом, что хватит писать на «голых» указателях, т.к. в современном C++ уже всё на смарт-поинтерах

Когда это заявляли, не имели в виду «тупо замените T* на unique_ptr<T> в своём коде grep-ом», как это поняли некоторые с ICQ=55.

anonymous
()
Ответ на: комментарий от Bad_ptr

Это просто такой маркетинговый призыв к людям, которые давно пишут на С++, посмотреть в сторону смартпоинтеров.

Ах, вон оно что! Ввели в стандарт фичу, которая рассматривается как шаг вперёд, но которая, на самом деле, не умеет в ковариантность. Так оказывается, это маркетинг?! Лол. Ну так зачем тогда твердить на каждом углу о том, что на голых указателях писать уже не нужно в 2018 году, в то время как смарт-поинтеры эти самые голые указатели не заменяют? Причём, это можно было бы реализовать, но нет, предлагается писать ужасы в стиле CRTP, какие-то вариадики с множественным наследованием, какие-то приватные виртуальные функции? Лол. А всего то надо обеспечить ковариантность.

azelipupenko
() автор топика
Ответ на: комментарий от anonymous

Когда это заявляли, не имели в виду «тупо замените T* на unique_ptr<T> в своём коде grep-ом», как это поняли некоторые с ICQ=55.

Ну да. Ведь grep не умеет ничего заменять, как думают некоторые с IQ over 9000 :-)

azelipupenko
() автор топика
Ответ на: комментарий от pon4ik

Очевидно же, потому, что ты выбрал кейс для shared_ptr или какого нить ptr_view.

Не понял, причём тут shared_ptr?

azelipupenko
() автор топика

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

CatsCantFly
()
Ответ на: комментарий от CatsCantFly

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

В новых стандартах эта «бага» прекрасно работает. Значит, это не бага.

azelipupenko
() автор топика
Ответ на: комментарий от CatsCantFly

backward compatibility

Так это не бага, а главная фича цепепе.

azelipupenko
() автор топика
Ответ на: комментарий от azelipupenko

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

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

а вот если бы тебя в комитет и на зарплату
вот бы ты там жару дал
Написал бы «приказываю обеспечить ковариантность» и бедные компиляторописальщики со стоном вынуждены были бы выполнять требования твоего стандарта

или просто забить и дальше «необеспечивать коварантность» и спокойно жить

Bad_ptr ★★★★★
()
Ответ на: комментарий от pon4ik

Из того что гуглится семантика как раз больше похожа на `ptr_view/observer_ptr`

observer_ptr это же тупой невладеющий указатель, как T*.

polymorphic_value (indirect, clone_ptr, copy_ptr и т.д.) копирует то, на что «указывает» при копировании. При этом умеет хранить производные от базового класса в «указателе» на базовый класс. И копирует их правильным конструктором копирования (для производного, а не базового класса).

В общем, решает те же задачи, что костыль под названием «метод clone», только более удобно.

anonymous
()

А какие вы знаете проблемы со смарт-поинтерами в современном C++?

Они не нравятся azelipupenko.

Virtuos86 ★★★★★
()
Ответ на: комментарий от anonymous

А, ты про всё решение. Так то, да конструктор копирования это не такая джава головного мозга как clone.

Я то только про семантику указатель на обьект, которым владеет impl почему то подумал.

pon4ik ★★★★★
()
Ответ на: комментарий от anonymous

Хотя, если немного подумать - clone_ptr опирается на конструктор копирования. Его нельзя сделать виртуальным. Так что решения не равнозначны.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от pon4ik

???

Я же написал, polymorphic_value<B> умеет хранить D (отнаследованный от B) и дёргать его конструктор копирования при копировании.

anonymous
()

У меня такое ощущение, что ты читаешь какой-нибудь популярный блог про C++, сейчас дочитал до статьи про требования к типам результата при наследовании и проблемам при использовании умных указателей, и решил на радостях тему забабахать. Не исключено, что ты нашёл древний вариант, где та же ситуация была с auto_ptr.

Всё никак не угомонишься? Казалось бы, если C++ такой плохой, просто не пиши на нём. Пиши на чём ты там пишешь и радуйся! Но нет же, свербит у тебя.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

Да, но разница в том, что разный тип полиморфизма используется, как я понимаю. В случае clone решение о том как будет копироваться текущий обьект принимается в рантайме, а в случае polimorphic_value на этапе компиляции нет?

Вопрос в том, можно ли написать так:

// B : public A
using copyable polimorphic_value<A>;
copyable foo = new A;
foo = new B;
auto bar = foo;

Хотя, в принципе, пока писал, понял как можно было бы сделать и на этапе выполнения. Но пример автора вопрос не раскрывает.

pon4ik ★★★★★
()
Ответ на: комментарий от pon4ik

В случае clone решение о том как будет копироваться текущий обьект принимается в рантайме, а в случае polimorphic_value на этапе компиляции нет?

Нет.

Вопрос в том, можно ли написать так:

Да.

Хотя, в принципе, пока писал, понял как можно было бы сделать и на этапе выполнения.

Так метод известный. Если в shared_ptr<B> засунуть объект типа D (D : public B), то при уничтожении будет вызван деструктор D, даже если он не виртуальный.

anonymous
()

Кто-нибудь, поясните для тех, кто out of the loop, что тут вообще происходит? Со смарт-поинтерами компилятор не догоняет, что clone() — это один и тот же метод в наследованных классах?

nezamudich ★★
()
Последнее исправление: nezamudich (всего исправлений: 2)
Ответ на: комментарий от i-rinat

У меня такое ощущение, что ты читаешь какой-нибудь популярный блог про C++, сейчас дочитал до статьи про требования к типам результата при наследовании и проблемам при использовании умных указателей, и решил на радостях тему забабахать. Не исключено, что ты нашёл древний вариант, где та же ситуация была с auto_ptr.

Слишком много конспирологии. Не вариант.

Всё никак не угомонишься? Казалось бы, если C++ такой плохой, просто не пиши на нём. Пиши на чём ты там пишешь и радуйся! Но нет же, свербит у тебя.

Всё никак что-то.

azelipupenko
() автор топика
Ответ на: комментарий от anonymous

Не секретарша, а какая-то дивчiна, за давностью лет забыл никнейм. И левое мыло в профиле.

Dark_SavanT ★★★★★
()

Но стоит только превратить указатели в std::unique_ptr, как всё перестаёт собираться.

Что намекает что твой код - говно.

dixi

Dark_SavanT ★★★★★
()
Ответ на: комментарий от Dark_SavanT

Что намекает что твой код - говно.

Что намекает, отсутствие у тебя понятия о предмете разговора, и что тебе везде мерещится одно говно :-)

azelipupenko
() автор топика

Ведь если ув. эксперты, уполномоченные принимать решения в части изменения стандарта, ввели смарт-поинтеры в язык, громогласно заявив при этом, что хватит писать на «голых» указателях, т.к. в современном C++ уже всё на смарт-поинтерах, то почему же тогда с этими хвалёными стандартными смарт-поинтерами ломается ковариантность?

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

Во-вторых, смарты добавили не в язык, а в стандартную библиотеку. И тут они ведут себя точно так же, как и любые другие шаблонные классы. Соответственно, чтобы работал твой код, нужно сделать какой-то механизм указания вариантности(как в некоторых языках для generic'ов). А это уже довольно тяжеловесное изменение. Так что считай это компромиссом.

anonymous
()
Ответ на: комментарий от Dark_SavanT

А что не так с его кодом? Это же фича C++ - ковариантность возвращаемых значений виртуальных функций.

anonymous
()
Ответ на: комментарий от anonymous

А что не так с его кодом?

clone() не копирует, а создаёт новый объект дефолтным конструктором.

anonymous
()

Но стоит только превратить указатели в std::unique_ptr, как всё перестаёт собираться.

Используй unique_ptr<B> и будет тебе щастье

annulen ★★★★★
()
Ответ на: комментарий от anonymous

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

anonymous
()
Ответ на: комментарий от Dark_SavanT

Ага, в том числе мне мерещится, что ты даже не тролль, а цельный дерьмодемон.

Лол :-) Не стоит так переживать :-) Обратись в соответствующее учреждение :-) Тебе там помогут :-)

azelipupenko
() автор топика
Ответ на: комментарий от anonymous

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

Во-первых, призывают на каждом углу :-) «C++0x feels like a new language» :-) Везде и всюду твердится, что «ну уж в современном C++ не должно быть ни одного new/delete, так как это уже всё в прошлом или в легаси, а вот теперь то в стандарте есть смарт-поинтеры и make_unique/shared, так что давайте ребятки, юзайте их и будет вам (и нам) счастье» :-)

Во-вторых, смарты добавили не в язык, а в стандартную библиотеку.

Ах вон в чём дело :-) Т.е. когда говорится «современный язык C++» - это имеется в виду всё тот же старый добрый язык C++ плюс range-for и variadic templates и всякие прочие move semantic? :-) А стандартные смарт-поинтеры к современному C++ отношения не имеют, потому что они всего лишь в стандартной библиотеке :-) Лол :-) Я правильно понял? :-)

azelipupenko
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.