Форум программистов, компьютерный форум, киберфорум
Наши страницы

С++ для начинающих

Войти
Регистрация
Восстановить пароль
 
 
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
#1

Как удалить объект, который это попросил? - C++

13.06.2014, 14:43. Просмотров 749. Ответов 24
Метки нет (Все метки)

Сам вопрос возник, когда работал с Qt и их системой signal/slot. Проблема на С++ выглядела бы так:
Есть два объекта: А(асинхронный) и О(ожидающий).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
struct O
{
    A *a;
    int downloadsAmount;
    MainObject *parent;
    
    void run() // Этот метод запускается в отдельном потоке. После его окончания, поток завершается
    {
        a = new A(this);
        a->download(); // Так же создает ещё один поток для метода download();
    }
    
    void downloadFinished()
    {
        ++downloadsAmount;
        parent->data = a->data; // по некоторым причинам, Data не является указателем
        // После сохранения data в MainObject, поток А тоже завершится (на самом деле в методе download(O *parent), но не суть. Главное, что теперь копия данных в А осталась без именений - её никто не удалил. В идеале было бы сделать, как ниже :
        
        // delete a; // но так нельзя, ведь после этого метода поток вернется в методе структуры А. Да, там больше нет обращения к данным А, но всё равно - это неправильно. В моем случае, это ошибка.
    }
}
 
struct A
{
    Data d; // не указатель
    
    void download(O *parent)
    {
        /*скачиваем*/
        parent->downloadFinished();
    }
}
Как удалить объект А, созданный в другом потоке, который завершил свое исполнение? Единственное, что я придумал, это занести его в какой-то глобальный
C++
1
vector < BaseObject * > crap;
- и каждую итерацию чего-нибудь очищать этот вектор. Само собой для вектора понадобится мьютекс, иначе не thread-safe. Есть ли иное решение?
1
Лучшие ответы (1)
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
13.06.2014, 14:43
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Как удалить объект, который это попросил? (C++):

Что значит константный указатель на объект, указатель на константный объект, и как это можно использовать? - C++
Подскажите, что значит константный указатель на объект, указатель на константный объект, и как это можно использовать??

this это адресс объекта, а *this это сам объект. я всё правельно понял? - C++
this это адресс объекта, а *this это сам объект. я всё правельно понял?

Как удалить базовый объект? - C++
Пишу под symbian, здесь Mbase вроде интерфейсов C#: class Mbase { virtual void foo1()=0; virtual void foo2()=0; virtual ...

Как удалить объект через указатель? - C++
Делаю консольный тетрис. Задаю указатель на объект класса Block. В if создаю объект класса, а потом этот объект нужно удалить. как удалить...

Как удалить объект списка list? - C++
у меня есть pPlan - это указатель на класс Plan. Listabit - список, созданный в классе Plan . pPlan-&gt;Listabit;// вот я на него ссылаюсь ...

Как удалить объект по указателю на базовый класс? - C++
Допустим есть несколько классов: // абстрактный класс - введен для управления наследниками class A{ ... } // рабочий класс...

24
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 19:49  [ТС] #16
Kuzia domovenok, нельзя удалять себя же.
Renji, в этом и проблема, что выходит, удаляется объект с методом, который ещё выполняется. равносительно
C++
1
 delete this
практически
0
Tulosba
:)
Эксперт С++
4705 / 3240 / 297
Регистрация: 19.02.2013
Сообщений: 9,046
13.06.2014, 19:55 #17
Цитата Сообщение от nexen Посмотреть сообщение
C++
1
a = new A(this);
В современном C++ следует такого избегать (если конечно не используется Qt-подход с иерархией вложенных объектов). Как уже упоминал Trwsdf, следует обернуть в подходящий тип "умного" указателя, а не изгаляться с delete this. Мне кажется std::shared_ptr будет тут самым правильным вариантом.
0
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,269
13.06.2014, 20:00 #18
Renji, в этом и проблема, что выходит, удаляется объект с методом, который ещё выполняется.
Ну тогда радикально:
C++
1
2
3
4
5
6
7
static void download(O *parent)
{
    Data d;//каждый download в отдельном потоке, каждый d в отдельном стеке, new не нужен
    /*скачиваем*/
    parent->downloadFinished(d);
    //static функция, объекта нет, а раз объекта нет, то и delete не нужен
}
Как мне кажется std::shared_ptr будет тут самым правильным вариантом.
shared_ptr тоже вызовет непонравившийся ТС delete, просто неявно.
1
Tulosba
:)
Эксперт С++
4705 / 3240 / 297
Регистрация: 19.02.2013
Сообщений: 9,046
13.06.2014, 20:07 #19
Цитата Сообщение от Renji Посмотреть сообщение
shared_ptr тоже вызовет непонравившийся ТС delete, просто неявно.
ТС не понравился delete this, насколько я понял, а не delete как таковой. Отсутствие delete - утечка памяти.
0
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,269
13.06.2014, 20:19 #20
ТС не понравился delete this, насколько я понял, а не delete как таковой.
Как я понял, ТС нужно чтобы объект удалялся после завершения метода download, но не из метода download. Если поставить shared_ptr внутрь метода, он и объект прибьет внутри метода. Если поставить shared_ptr снаружи, он вообще ничего не прибьет. По крайней мере, в тот момент, когда это надо ТС.
0
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 20:34  [ТС] #21
Tulosba,

Не по теме:

почему так лучше не делать? Закинул другому классу указатель на "родителя"


Как уже писал выше, умный указатель не поможет.
Renji, как вариант, но статический класс ради такого.. Сработает, но выглядит страшно (:
Tulosba, опять-таки, разве delete this не UB?
Renji,

давайте я немного изменю условие. Есть объекты классов А и В, как в примере. ВНЕЗАПНО, появился поток, исполняющий download() класса В, который в конце этого метода перестанет существовать. Как этому потоку, исполняющему метод класса В удалить объект класса В?
Как уже писал выше, способ
C++
1
 vector < Object* > crap
не подходит по причине того, что нельзя точно узнать, завершился ли поток (signal/slot в Qt в асинхронном режиме)
0
Kuzia domovenok
2128 / 1956 / 195
Регистрация: 25.03.2012
Сообщений: 6,809
Записей в блоге: 1
13.06.2014, 20:49 #22
Да ладно? Где это сказано, что delete this нельзя делать? Если после dеlеtе гарантированно не происходит обращений к полям данного объекта, то вполне можно!
1
Renji
2113 / 1472 / 346
Регистрация: 05.06.2014
Сообщений: 4,269
13.06.2014, 20:50 #23
давайте я немного изменю условие. Есть объекты классов А и В, как в примере. ВНЕЗАПНО, появился поток, исполняющий download() класса В, который в конце этого метода перестанет существовать. Как этому потоку, исполняющему метод класса В удалить объект класса В?
Для удаления объекта класса B требуется:
1) Убедиться что на него больше никто не ссылается/не ссылался изначально/обнулить все ссылки на объект.
2) Выполнить delete.
Один у вас поток или несколько, ничего принципиально не меняется.
0
nexen
187 / 180 / 3
Регистрация: 27.01.2012
Сообщений: 1,335
13.06.2014, 21:17  [ТС] #24
Kuzia domovenok, примерно с год-два назад здесь и научили меня сторожилы, что нельзя delete this, даже если не происходит ничего после.
0
Убежденный
Ушел с форума
Эксперт С++
15933 / 7243 / 1140
Регистрация: 02.05.2013
Сообщений: 11,637
Записей в блоге: 1
Завершенные тесты: 1
13.06.2014, 21:35 #25
Лучший ответ Сообщение было отмечено автором темы, экспертом или модератором как ответ
this - это просто указатель на объект класса.
Если this указывает на объект, созданный в динамической памяти, к
нему вполне допустимо применять конструкцию "delete this", что
эквивалентно "delete ptr_to_object". Ни к каким побочным эффектам или
неопределенному поведению это не приведет. Такая конструкция
повсеместно используется, например, в COM. Там объект разрушает
сам себя, когда его счетчик ссылок становится равным нулю.
1
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
13.06.2014, 21:35
Привет! Вот еще темы с ответами:

Нужно удалить слова как это сделать? - C++
Есть такой текст &quot;for do while int void using while&quot; нужно удалить слова &quot;while&quot; как это сделать?

Как удалить символ перевода строки, который оставляет cin - C++
Как удалить символ перевода строки, который оставляет cin. Нужно вводить в строчку чаровые переменные, и чтобы они так в строке и...

Как удалить каталог, который имеет вложеные папки и файлы? - C++
С помощью каких средств это можно реализовать? Есть функция _rmdir(const char*) в direct.h, но она удаляет только пустой каталог. Я...

Не получается удалить минимальный элемент в массиве и вывести новый. Как сделать это? - C++
#include &quot;stdafx.h&quot; #include &lt;iostream&gt; #include &lt;locale&gt; using namespace std; int main() { setlocale( LC_ALL,&quot;Russian&quot; ); ...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
25
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru