Pull to refresh
31
0
Александр Дубовик @Dubovik_a

С++

Send message

Звонит как-то Моня Саре:

  • Сара, как там Миша?

  • Ой, ты знаешь, кладовщиком устроился. Зарплата 250 долларов, ну и, конечно, немного сверху.

  • А как там Фаина?

  • Пошла завсекцией в магазин. Зарплата 300 долларов, ну и, конечно, немного сверху.

  • А как Хаим?

  • Программистом пошёл. Зарплата 4800 долларов. Но, ты представляешь - ничего сверху.

  • Оххх, и как же он жить-то будет...

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

Однако, использование std::enable_shared_from_this не является обязательным при использовании std::shared_ptr.
По поводу custom deleter — «не поддерживает» и «не возможно сказать устновлен ли» — это разные характеристики, не правда ли?

Вот тут Вы не правильно поняли.

В статье я говорю, что невозможно сказать, как именно поведёт себя экземпляр std::shared_ptr, т.е. как он создан — с помощью конструктора или с помощью std::make_shared. Разница в поведении существенная (настолько существенная, что это могли бы быть даже разные статические типы), а выяснить это нельзя.
Существенная часть посыла статьи: «контекст, в котором родился std::make_shared, существенно изменился с приходом c++17».

Далее, Вы говорите про производительность.
Да, это важный параметр.
Но:
— std::make_shared не гарантирует повышение производительности. Если бы была функция std::make_single_allocation_shared — вот тогда да, в точку;
— с нехваткой производительности на std::shared_ptr реально столкнуться тогда, когда их в самом деле 100 000. И если бы я на практике такое встретил — выруливал бы не в сторону экономии одной аллокации (всё равно ведь не спасёт), а действительно, как говорит destman, или в сторону кастомного решения со строго необходимым функционалом, или в сторону уменьшения количества разделяемых объектов до единиц — десятков.
Вы можете себе представить задание типа «давайте сделаем очень быструю программу, а если будет падать — ну ничего страшного, пользователи переживут»?

Про особенности вычисления аргументов тему я тоже поднял. Именно потому, что это важно и в данном контексте, и вообще для разработчика c++.
Мне вот не совсем понятно.
Почему не использовать std::unique_ptr? Неужели вам в самом деле надо разделять владение? А если и так — почему надо разделять владения 100 000 объектов, а не одного объекта, содержащего 100 000 элементов?
Нет, не так.
Я начал с истоков — почему std::make_shared был прямо жизненно необходим. Потому что утечки — это серьёзная проблема. И с утечками sdt::make_shared действительно борется успешно. Или боролся. До c++17. И до c++17 действительно можно было просто применять std::make_shared, даже толком не вникая в подробности. Потому что это решало критичный, первостепенный вопрос. Не читая документации, не разбираясь — просто применять готовый рецепт.

А Вы сейчас — про производительность.
Так вот, производительность — вопрос вторичный. Кому-то может её хватать, а кому-то — нет. Способов оптимизации — масса. Критичность недостаточной производительности как правило намного ниже, чем текущей памяти, которая может заканчиваться крэшами.
Одна аллокация и деаллокация вместо двух — это положительная сторона медали (но, заметьте — она не гарантирована). Но она же обязательно влечёт вторую сторону, отрицательную.
Будет ли для вас отрицательная сторона заметна — это вопрос.
Как впрочем и положительная.
Но это совсем не повод утверждать, что отрицательное — это не отрицательное, или что его нет.

Просто документацию читать надо перед тем, как что-то использовать

Статьи на хабре вообще не нужны. Учебники тоже. И комментарии. И обсуждения. И форумы. Это всё для слабаков, которые не умеют читать справочники.
Это довольно странная и неочевидная особенность, что способ создания существенно влияет на поведение объекта, при этом спросить объект в рантайме «ты чьих будешь» никак нельзя.
Ссылку в студию.
Универсальностью и архитектурным изяществом этот подход не блещет, но для ограниченного специального применения действительно может сгодиться.
Т.е. этот умный указатель предъявляет требования к хранимым типам? И совсем не способен хранить без обёртки простые типы, контейнеры стандартной библиотеки, классы сторонних библиотек?
А можете объяснить подробнее, как это счётчик «лежит в объекте» и при этом разделяется между несколькими копиями умного указателя?
Возможность не писать тип два раза — да, есть такое. Но это просто мелочь по сравнению с остальными вопросами, рассмотренными в статье.
Нет, всё корректно.
if statement
«declaration of a single non-array variable with a brace-or-equals initializer»
Спасибо, в самом деле, моя ошибка.
Исправил статью.
И дополнил в соответствии с возможностью поуправлять ещё одним возвращаемым значением.
Плюсик Вам в карму.
Как на такой скорости кристалл не скалывается?
Прям очень круто.
Про ТБ желательно всё же указывать.
Я бы даже ещё подробнее расписал проблему.
Вроде бы можно написать operator|| для указателей на функции.
Но нет. Потому что это встроенный тип.

Код
#include <vector>
#include <functional>

template<typename ... Args>
using Pred = bool (*) (Args ...);

template<typename ... Args>
std::function<bool(Args ...)> operator||(Pred<Args ...> op1, Pred<Args ...> op2)
{
    return [op1, op2](Args ... args) {return op1(args ...) || op2(args ...);};
}

bool isMultipleOf2(int n)
{
    return (n % 2) == 0;
}

bool isMultipleOf3(int n)
{
    return (n % 3) == 0;
}

int main() {
    auto orr = operator||(&isMultipleOf2, &isMultipleOf3);

    return 0;
}


Более-менее внятную диагностику дают Clang и MSVC.

www.godbolt.org/z/UraL8c
1
23 ...

Information

Rating
Does not participate
Location
Минск, Минская обл., Беларусь
Registered
Activity