1. C++ / Говнокод #24565

    0

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    #include <iostream>
    #include <memory>
    #include <thread>
    #include <chrono>
    #include <mutex>
     
    struct Base
    {
        Base() { std::cout << "  Base::Base()\n"; }
        // Note: non-virtual destructor is OK here
        ~Base() { std::cout << "  Base::~Base()\n"; }
    };
     
    struct Derived: public Base
    {
        Derived() { std::cout << "  Derived::Derived()\n"; }
        ~Derived() { std::cout << "  Derived::~Derived()\n"; }
    };
     
    void thr(std::shared_ptr<Base> p)
    {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        std::shared_ptr<Base> lp = p; // thread-safe, even though the
                                      // shared use_count is incremented
        {
            static std::mutex io_mutex;
            std::lock_guard<std::mutex> lk(io_mutex);
            std::cout << "local pointer in a thread:\n"
                      << "  lp.get() = " << lp.get()
                      << ", lp.use_count() = " << lp.use_count() << '\n';
        }
    }
     
    int main()
    {
        std::shared_ptr<Base> p = std::make_shared<Derived>();
     
        std::cout << "Created a shared Derived (as a pointer to Base)\n"
                  << "  p.get() = " << p.get()
                  << ", p.use_count() = " << p.use_count() << '\n';
        std::thread t1(thr, p), t2(thr, p), t3(thr, p);
        p.reset(); // release ownership from main
        std::cout << "Shared ownership between 3 threads and released\n"
                  << "ownership from main:\n"
                  << "  p.get() = " << p.get()
                  << ", p.use_count() = " << p.use_count() << '\n';
        t1.join(); t2.join(); t3.join();
        std::cout << "All threads completed, the last one deleted Derived\n";
    }

    https://en.cppreference.com/w/cpp/memory/shared_ptr

    Объясните почему "reset" не грохнул инстанс в других потоках?

    Запостил: guestinxo, 02 Августа 2018

    Комментарии (22) RSS

    • Переведи на "SQL", ибо я не понимаю "C++".
      Ответить
    • https://ru.cppreference.com/w/cpp/thread/thread/thread

      > 3) Создает новый объект std::thread и связывает его с потоком выполнения. Первый конструктор копирует все аргументы args... в локальную память потока, как функция:

      Ты передаешь туда shared_ptr, который конструктор thread копирует.

      А shared_ptr удаляет указываемый объект, когда на него больше нету ссылок.
      https://ru.cppreference.com/w/cpp/memory/shared_ptr
      Ответить
    • Собственно, вызов reset просто уменьшает количество ссылок на одну, а у тебя остается еще 3. В каждом экземпляре thread.
      Но твой объект Base будет удален, как только деструтурируются все 3 этих объекта.
      Ответить
      • > Собственно, вызов reset просто уменьшает количество ссылок на одну

        В примере видно, что p.use_count() равно 0 до того, как потоки начали выполняться
        Ответить
        • Но он должен вести себя соответственно семантике подсчета ссылок.
          А именно сбрасывать use_count на значение меньшее на единицу. Как это происходит при завершении потоков.

          Почему же use_count после вызова reset устанавливается в 0 -- непонятно.
          Ответить
          • Потому что
            ownership from main:
              p.get() = (nil), p.use_count() = 0

            После reset() указатель обнулился, use_count() уже относится не к созданному когда-то экземпляру, а как бы к нулевому указателю. Это ж не release() (которого, естественно, нет).
            Ответить
    • Тут более интересно
      // Note: non-virtual destructor is OK here

      Но это тоже понятно. На самом деле мы можем вообще написать
      class Base; // Forward declaration
      class A
      {
      public:
        std::shared_ptr<Base> m_basePointer;
      
        A();
        ~A();
      };

      И Base будет коррекно разрушен в деструкторе. Единственное - деструктор должен быть явно реализован в cpp-файле, поскольку автоматически сгенерированный деструктор не скомпилируется.
      Ответить
    • Объясните дурачку из Питонии, в чём разнится мужду struct и class в плюсах?
      Ответить
      • Здесь была хуета
        Ответить
      • Полез гуглить. Нашёл ответ на SO. Всего два отличия:
        1. Члены класса, определенного с помощью ключевого слова class, по умолчанию являются private. Члены класса, определенного с помощью ключевого слова struct или union, по умолчанию являются public.

        2. При отсутствии спецификатора доступа (т.е. private/protected/public) у базового класса, базовый класс будет public если класс определен с помощью struct и private если класс определен с помощью class.


        Изначально struct была чистой структурой, аналогом записи (record) в Паскале. Потом в неё нафигачили методов, виртуальных методов, конструкторов, деструкторов... — в итоге получили class. Единственным отличием осталось public/private по умолчанию.
        Ответить
        • Упс, а у struct могут быть private члены? Фак.
          Ответить
        • >>>"SO"

          Если что, его сервера работают под управлением "Windows".
          Ответить
          • Если что, SO написан на C# (а не на "PHP")
            Ответить
            • По ошибке.
              Ответить
            • Точно? А исходники есть? А то вдруг он написан с использованием технологии "ASP"?
              Ответить
              • Спольски писал как-то про это, могу нагуглить.

                Он действительно долго очень писал на asp classic (язык VBS), но потом перешел на ASP.NET и C#
                Ответить
              • https://www.insight-it.ru/highload/2010/arkhitektura-stack-overflow/

                Microsoft ASP.NET MVC
                SQL Server 2008
                C#
                Visual Studio 2008 Team Suite
                Ответить

    Добавить комментарий