|
Заблокирован
|
|||||||||||
Можно ли удалить объект экземпляра класса из самого себя?18.11.2014, 15:10. Показов 17492. Ответов 67
Метки нет (Все метки)
Привет!
Допустим:
![]() Добавлено через 4 минуты Вот так вроде работает, но как - то это ..... Так память нормально освобождается?
![]() Добавлено через 4 минуты Нашёл себе методичку: http://www.parashift.com/c++-f... -this.html
0
|
|||||||||||
| 18.11.2014, 15:10 | |
|
Ответы с готовыми решениями:
67
Удаление экземпляра класса в функции самого класса (Ошибка при отладке) как сделать чтобы объект производного класса сам себя добавлял в список или массив указателей базового класса? |
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
||||||||||||
| 19.11.2014, 22:43 | ||||||||||||
0
|
||||||||||||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|
| 19.11.2014, 22:48 | |
|
0
|
|
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
|
| 19.11.2014, 22:51 | |
|
1
|
|
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|
| 19.11.2014, 22:53 | |
|
0
|
|
|
Форумчанин
8217 / 5048 / 1437
Регистрация: 29.11.2010
Сообщений: 13,453
|
||
| 20.11.2014, 01:12 | ||
|
Да, delete this не является хорошей практикой, но с точки зрения стандарта всё ок.
0
|
||
|
Ушел с форума
|
||
| 20.11.2014, 09:21 | ||
|
явно следует, что "delete this" (не из деструктора !) - UB.
0
|
||
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
||||||||||||||||
| 23.11.2014, 01:57 | ||||||||||||||||
|
Кстати, вызов метода по невалидному указателю так же является UB
Однако UB не означает, что непременно программа должна рухнуть. UB означает "поведение не определено". Другими словами никто вам больше ничего не гарантирует. Вся ответственность полностью на плечах программиста. Как программист, который знает что делает, вы можете рассуждать о любых возможных "если". Это уже ваше личное дело. И даже если вы решили, что в данной ситуации беды не должно быть, от этого UB не перестает быть UB.
Если вам это интересно, то вы можете попробовать загуглить на хабре. Там вроде бы были какие то ссылки на стандарт. Ну или вы можете проверить следующую информацию:
0
|
||||||||||||||||
|
19506 / 10109 / 2464
Регистрация: 30.01.2014
Сообщений: 17,834
|
|||||
| 23.11.2014, 03:04 | |||||
|
В общем, как понимать эту фразу? Да, в определенных ситуациях, delete this может привести к последующему UB: 1) Вызов из деструктора. 2) Вызов метода или обращение к данным следом за delete this. В иных случаях оно к UB, увы, не приводит.
0
|
|||||
|
Неэпический
|
|
| 23.11.2014, 05:53 | |
|
delete this вполне легальная штука.
Но нужно точно знать, что: - объект выделен с помощью new - далее данный объект не будет нигде и никем использоваться, в том числе и в данной функции, после delete this delete this не приводит к UB, а вот использование this после сие действа обернется катастрофой.
0
|
|
|
4226 / 1799 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
| 23.11.2014, 06:00 | |
|
По идее delete this и должен быть валиден, так как this - это указатель. ИМХО чтоб эту фичу юзать, странное нужно приложение ещё с той архитектурой, так как в обычных она не нужна.
0
|
|
|
Неэпический
|
|||||||
| 23.11.2014, 06:05 | |||||||
0
|
|||||||
|
Ушел с форума
|
|||||
| 23.11.2014, 10:29 | |||||
|
что "delete this" ведет к неопределенному поведению. Ни явно, ни косвенно. И зачем Хабр ? Давайте заглянем на более авторитетный в таких вопросах ресурс - isocpp.org: Memory Management https://isocpp.org/wiki/faq/fr... elete-this
Только к "delete this" это не имеет никакого отношения.
2
|
|||||
|
4226 / 1799 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
|
| 23.11.2014, 10:37 | |
|
0
|
|
| 23.11.2014, 11:09 | |
|
Можно
0
|
|
|
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
|
|||||
| 23.11.2014, 12:02 | |||||
|
Оптимизирующий компилятор закладывается на то, что this всегда валидный (иначе - это UB). А значит делать проверку не обязательно. И выпиливает её. Или поведение не определено. Речь о последствиях. После уничтожения объекта, this становится невалиден.
0
|
|||||
|
4226 / 1799 / 211
Регистрация: 24.11.2009
Сообщений: 27,562
|
||||||
| 23.11.2014, 12:13 | ||||||
|
Кстати, указателю this нельзя после delete this присвоить NULL.
0
|
||||||
|
3258 / 2060 / 351
Регистрация: 24.11.2012
Сообщений: 4,909
|
|
| 23.11.2014, 12:14 | |
|
0
|
|
|
Неэпический
|
|||||||||||||||||||||||||||
| 23.11.2014, 13:18 | |||||||||||||||||||||||||||
|
Спёрто из книги Дональд Бокс - Сущность технологии COM (крышка 1)
Оказывается, применение техники разделения интерфейса и реализации может решить и проблемы совместимости транслятора/компоновщика C++. При этом, однако, определение класса интерфейса должно принять несколько иную форму. Как отмечалось ранее, проблемы совместимости возникают из-за того, что разные трансляторы имеют различные соображения по поводу того, как 1. передавать особенности языка на этапе выполнения; 2. символические имена будут представлены на этапе компоновки. Если бы кто-нибудь придумал, как скрыть детали реализации транслятора/компоновщика за каким-либо двоичным интерфейсом, это сделало бы написанные на C++ библиотеки DLL значительно более широко используемыми. Двоичная защита, то есть тот факт, что класс интерфейса C++ не использует языковых конструкций, зависящих от транслятора, решает проблему зависимости от транслятора/компоновщика. Чтобы сделать эту независимость более полной, необходимо в первую очередь определить те аспекты языка, которые имеют одинаковую реализацию в разных трансляторах. Конечно, представление на этапе выполнения таких сложных типов, как С-структуры (structs), может быть выдержано инвариантным по отношению к трансляторам. Это — основное, что должен делать системный интерфейс, основанный на С, и иногда это достигается применением условно транслируемых определений типа прагм (pragmas) или других директив транслятора. Второе, что следует сделать, — это заставить все компиляторы проходить параметры функций в одном и том же порядке (слева направо, справа налево) и зачищать стек также одинаково. Подобно совместимости структур, это также решаемая задача, и для унификации работы со стеком часто используются условные директивы транслятора. В качестве примера можно привести макросы из Win32 API. Каждая извлеченная из системных DLL функция определена с помощью этих макросов:
Третье требование к независимости трансляторов — наиболее уязвимое для критики из всех, так как оно делает возможным определение двоичного интерфейса: все трансляторы C++ с заданной платформой одинаково осуществляют механизм вызова виртуальных функций. Действительно, это требование единообразия применимо только к классам, не имеющим элементов данных, а имеющим не более одного базового класса, который также не имеет элементов данных. Вот что означает это требование для следующего простого определения класса:
Впрочем, это не такое уж блестящее решение проблемы, как может показаться. Реализация виртуальных функций на C++ на этапе выполнения выливается в создание конструкций vptr и vtbl практически на всех трансляторах. При этой методике транслятор молча генерирует статический массив указателей функций для каждого класса, содержащего виртуальные функции. Этот массив называется vtbl (virtual function table — таблица виртуальных функций) и содержит один указатель функции для каждой виртуальной функции, определенной в данном классе или в ее базовом классе. Каждый объект класса содержит единственный невидимый элемент данных, именуемый vptr (virtual function pointer - указатель виртуальных функций); он автоматически инициализируется конструктором для указания на таблицу vtbl класса. Когда клиент вызывает виртуальную функцию, транслятор генерирует код, чтобы разыменовать указатель vptr, занести его в vtbl и вызвать функцию через ее указатель, найденный в назначенном месте. Так на C++ обеспечивается полиморфизм и диспетчеризация динамических вызовов. Рисунок 1.5 показывает представление на этапе выполнения массивов vptr/vtbl для класса calculator, рассмотренного выше. Фактически каждый действующий в настоящее время качественный транслятор C++ использует базовые концепции vprt и vtbl. Существует два основных способа размещения таблицы vtbl: с помощью CFRONT и корректирующего переходника ( adjuster thunk). Каждый из этих приемов имеет свой способ обращения с тонкостями множественного наследования. К счастью, на каждой из имеющихся платформ доминирует один из способов (трансляторы Win32 используют adjuster thunk, Solaris — стиль CFRONT для vtbl). К тому же формат таблицы vtbl не влияет на исходный код C++, который пишет программист, а скорее является артефактом сгенерированного кода. Желающие узнать подробности об этих двух способах могут обратиться к прекрасной книге Стэна Липпмана "Объектная модель C++ изнутри" (Stan Lippman. Inside C++ Object Model). Основываясь на столь далеко идущих допущениях, теперь можно решить проблему зависимости от транслятора. Предполагая, что все трансляторы на данной платформе одинаково реализуют механизм вызова виртуальной функции, можно определить класс интерфейса C++ так, чтобы глобальные операции над типами данных определялись в нем как виртуальные функции; тогда можно быть уверенным, что все трансляторы будут генерировать эквивалентный машинный код для вызова методов со стороны клиента. Это предположение об единообразии означает, что ни один класс интерфейса не имеет элементов данных и ни один класс интерфейса не может быть прямым потомком более чем одного класса интерфейса. Поскольку в классе интерфейса нет элементов данных, эти методы практически невозможно использовать.
Определение этих методов как чисто виртуальных также дает знать транслятору, что от класса интерфейся не требуется никакой реализации этих методов. Когда транслятор генерирует таблицу vtbl для класса интерфейса, входная точка для каждой простой виртуальной функции является или нулевой ( null), или точкой входа в С-процедуру этапа выполнения (_purecall в Microsoft C++), которая при вызове генерирует логическое утверждение. Если бы метод не был определен как чисто виртуальный, транслятор попытался бы включить в соответствующую входную точку vtbl системную реализацию метода класса интерфейса, которая в действительности не существует. Это вызвало бы ошибку компоновки. Определенный таким образом класс интерфейса является абстрактным базовым классом. Соответствующий класс реализации должен порождаться классом интерфейса и перекрывать все чисто виртуальные фyнкции содержательными реализациями. Эта наследственная связь проявится в объектах, которые в качестве своего представления имеют двоичное надмножество представления класса интерфейса (которое как раз и есть vptr/vtbl). Дело в том, что отношение "является" ("is-a") между порождаемым и базовым классами применяется на двоичном уровне в C++ так же, как и на уровне моделирования в объектно-ориентированной разработке:
Поскольку FastString порождается от IFastString , двоичное представление объектов FastString должно быть надмножеством двоичного представления IFastString . Это означает, что объекты FastString , будут содержать указатель vptr, указывающий на совместимую с таблицей vtbl IFastString. Поскольку классу FastString vptr можно приписывать различные конкретные типы данных, его таблица vtbl будет содержать указатели на существующие реализации методов Length и Find. Их связь показана на рис. 1.6.
0
|
|||||||||||||||||||||||||||
|
Неэпический
|
|||||||||||||||||||||||||||||||
| 23.11.2014, 13:20 | |||||||||||||||||||||||||||||||
|
Спёрто из книги Дональд Бокс - Сущность технологии COM (крышка 2)
Даже несмотря на то, что открытые операторы над типами данных подняты до уровня чисто виртуальных функций в классе интерфейса, клиент не может приписывать значения объектам FastString, не имея определения класса для класса реализации. При демонстрации клиенту определения класса реализации от него будет скрыта двоичная инкапсуляция интерфейса; что не позволит клиенту использовать класс интерфейса. Одним из разумных способов обеспечить клиенту возможность использовать объекты FastString является экспорт из DLL глобальной функции, которая будет вызывать новый оператор от имени клиента. При условии, что эта подпрограмма экспортируется с опцией extern "С" , она будет доступна для любого транслятора C++.
Последнее препятствие, которое предстоит преодолеть, относится к уничтожению объекта. Следующая клиентская программа пройдет трансляцию, но результаты будут непредсказуемыми:
Очевидное решение этой проблемы — сделать деструктор виртуальным в классе интерфейса. К сожалению, это нарушит независимость класса интерфейса от транслятора, так как положение виртуального деструктора в таблице vtbl может изменяться от транслятора к транслятору. Одним из конструктивных решений этой проблемы является добавление к интерфейсу явного метода Delete как еще одной чисто виртуальной функции, чтобы заставить производный класс уничтожать самого себя в своей реализации этого метода. В результате этого будет выполнен нужный деструктор. Модифицированная версия заголовочного файла интерфейса выглядит так:
Рисунок 1.7 показывает представление FastString на этапе выполнения. Чтобы использовать тип данных FastString, клиентам надо просто включить в программу файл определения интерфейса и вызвать CreateFastString:
Отметим, что все, кроме одной, точки входа в DLL FastString являются виртуальными функциями. Виртуальные функции класса интерфейса всегда вызываются косвенно, через указатель функции, хранящийся в таблице vtbl, избавляя клиента от необходимости указывать их символические имена на этапе разработки. Это означает, что методы интерфейса защищены от различий в коррекции символических имен на разных трансляторах. Единственная точка входа, которая явно компонуется по имени, — это CreateFastString — глобальная функция, которая обеспечивает клиенту доступ в мир FastString. Заметим, однако, что эта функция была экспортирована с опцией extern "С", которая подавляет коррекцию символов. Следовательно, все трансляторы C++ ожидают, что импортируемая библиотека и DLL экспортируют один и тот же идентификатор. Полезным результатом этой методики является то, что вы можете спокойно извлечь класс из DLL, использующей одну среду C++, а обратиться к этому классу из любой другой среды C++. Эта возможность необходима при построении основы для независимых от разработчика компонентов повторного пользования.
0
|
|||||||||||||||||||||||||||||||
| 23.11.2014, 13:20 | |
|
Можно ли заставить класс записывать самого себя в файл? Как можно удалить или очистить тело макроса после его исполнения из самого себя?
Зацыкливания класса на самого себя Как экземпляру класса изменить тип самого себя? Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Транслитерация текста с кириллицы на латиницу (вариант №2)
Maks 13.11.2026
Обновленная версия ранее созданной обработки.
Добавлено:
- Проверка исходного текста на кириллицу, через обращение к стандартной функции "ТолькоКириллицаВСтроке" из общего модуля. . .
|
Часы с термометром и праздничным календарем
yariko 12.11.2026
Сегодня мы рассмотрим как можно сделать отличные многофункциональные часы.
Итак, поставим конкретную задачу: разработать часы с календарем, двумя термодатчиками, выводом поздравительных сообщений. . .
|
Транслитерация текста с кириллицы на латиницу (вариант №1)
Maks 11.11.2026
Решил облегчить жизнь себе и коллегам админам при создании электронных почтовых ящиков для пользователей, в результате написал обработку "Транслитерация текста" с кириллицы на латиницу, а в ней. . .
|
Книги по геймдизайну, левел-дизайну, игровым механикам и проектированию игрового опыта
8Observer8 08.11.2026
Содержание блога | English Version
1. 2003 - 06 - Designing Virtual Worlds (1st Edition)
Автор: Richard A. Bartle | Объем: 768 стр.
Ссылки: Amazon
. . .
|
|
Родители токсичные абьюзеры по отношению к своим детям ругают их оскорбляют не любят
zorxor 08.11.2026
Жить в атмосфере постоянных оскорблений, критики и холодности со стороны родителей — это тяжелое и болезненное испытание, которое оставляет глубокие эмоциональные раны. Токсичное и абьюзивное. . .
|
Как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы. Ответ от Джемени ИИ.
zorxor 08.11.2026
Джемени, как только я захожу к себе в свою комнату я сразу же с себя снимаю свои трусы.
Многие люди, возвращаясь домой, сразу переодеваются в максимально свободную одежду или вовсе предпочитают. . .
|
Паттерн очереди действий/команд (Action / Command Queue). Система очереди действий и кат-сцен с SDL3 Callbacks, cglm и OpenGL
8Observer8 07.11.2026
Содержание блога | English Version
Руководство для начинающих по реализации паттерна очереди действий/ команд (Action / Command Queue) на C++ (C++20) с использованием официального SDL3 Callbacks. . .
|
Проверка полного ФИО в типовом справочнике
Maks 07.11.2026
Решение реализовано в конфигурации КА2, на примере справочника "КонтактныеЛицаПартнеров".
Задача:
Запрет инициалов.
Не допускаеть использование сокращений вида "И. И. ", "И. И. ", "И И" и. . .
|