Objective-C классы в структурах с ARC

Я попытался сделать структуру с классами в ней, например:

struct my_struct
{
    NSString *string;
    // more fields
};

К моему удивлению, Objective-C ++ разрешил это с поддержкой ARC.
Как это будет управлять строкой?
Он может легко сохраняться в каждом задании, но проблема - проблема.
Он может добавить деструктор с выпуском в нем, но это сделает структуру нетривиальной.
Он также может сделать это не сохранением или выпуском, но для этого должно быть небезопасно.

Из моего наблюдения ничто не падает при использовании этого, но я хотел бы знать, что на самом деле происходит здесь.

Ответ 1

См. 4.3.5 документов ARC:

4.3.5. Области, структурированные и объединенные в собственность,

Программа плохо сформирована, если объявляет член структуры или объединения C чтобы иметь нетривиальный тип собственности.

Обоснование: результирующий тип будет не-POD в смысле С++, но C не дает нам очень хороших языковых инструментов для управления временем жизни агрегатов, поэтому удобнее просто запретить их. это все еще можно управлять этим с помощью void * или __unsafe_unretained объект.

Это ограничение не применяется в Objective-C ++. Однако нетривиально типы, имеющие отношение к собственности, считаются не-POD: в терминах С++ 11 они не тривиально по умолчанию конструктивны, скопированы конструктивные, перемещаются конструктивный, назначаемый экземпляр, перенос назначаемого или разрушаемого. Это является нарушением правила С++ One Definition для использования класса вне ARC, которая в соответствии с ARC будет иметь нетривиальную собственность член.

Обоснование: в отличие от C, мы можем выразить всю необходимую ARC-семантику для подобъектов, относящихся к собственности, в качестве подопераций (по умолчанию) специальные функции-члены для класса. Затем эти функции становятся нетривиальный. Это имеет неочевидный результат, который класс будет иметь нетривиальный конструктор копирования и нетривиальный деструктор; если это обычно не будет истинным вне ARC, объекты типа будут передан и возвращен ABI-несовместимым образом.

Если вы прочитаете все предостережения, я настоятельно рекомендую не делать этого в ObjС++. В любом случае я настоятельно рекомендую не использовать ObjС++. Это мостиковый язык, который помогает чистым ObjC и чистым С++ разговаривать друг с другом. У него много проблем. Объединение ObjС++ с ARC представляет затраты времени и пространства, которые не встречаются в ObjC, чтобы сделать его безопасным для исключений. Определение этих типов структур данных, специфичных для ObjС++, затрудняет взаимодействие с кодом, отличным от ObjС++, и кодом, отличным от ARC (обратите внимание на предостережение, что вы не можете использовать это вне ARC). Многое из того, что вы должны получить бесплатно от ARC, внезапно становится тяжелым, так как вам снова нужно беспокоиться об управлении памятью (как вы уже обнаружили).

Создайте чистый слой ObjC. Создайте чистый слой С++. Создайте тонкий слой ObjС++, чтобы связать их вместе. Не ставьте объекты ObjC в структуры и, определенно, не в каких-либо публичных структурах (т.е. Видимых вне одного объекта ObjС++, который его определяет).