Как делают я *не* удаляю участника в деструкторе?

Главные инструкции подобны любому другому большому проекту кода. Приложения должны обратиться к единственной, ясно определенной ответственности. Имя "приложение" является неправильным употреблением; приложений Django нужно думать больше как допускающие повторное использование компоненты, которые могут быть включены вместе для создавания реального приложения. Тесты для каждого приложения должны содержаться в рамках того приложения. Приложения должны быть разъединены друг от друга максимально как можно больше, но ясно будут зависимости, таким образом, цель должна будет состоять в том, чтобы сохранить граф зависимостей максимально простым и нормальным.

я предпочитаю сохранять все шаблоны для проекта в соответствии с единственным шаблонным каталогом всего проекта, с подкаталогом для каждого приложения (использующий шаблонный подкаталог для каждого приложения очень сильное соглашение в Django, поскольку это избегает шаблонных коллизий имени между приложениями). Причина единственного шаблонного каталога всего проекта состоит в том, что шаблоны, шаблонные деревья наследования и имена блока могут быть довольно определенными для проекта, таким образом, трудно обеспечить шаблоны приложений "по умолчанию", которые могут включить к любому проекту. Были некоторые попытки обосноваться на стандартных соглашениях о присвоении имен для основы, по всему сайту обрабатывает по шаблону и блоки, которые они определяют, но я не видел, что стандарт появляется все же (путь они переделывают вещи в , Pinax является, вероятно, самым близким, мы имеем к стандарту).

Ре "представляет воплощение в виде строки", если Вы имеете в виду i18n и l10n, у Django есть мощная поддержка этого и стандартных мест, куда это помещает .po файлы - проверяют эти документы .

6
задан Brian Tompsett - 汤莱恩 3 July 2015 в 19:29
поделиться

11 ответов

Краткий ответ : Нет.

Более длинный ответ : Если "member" на самом деле является указателем на какое-то другое выделение, вы можете сделать так, чтобы другое выделение не удалялось.

Но обычно, если вы выделяете другой блок в конструкторе, вы хотите удалить его в деструкторе. Все остальное потребует осторожного обращения с «владением» рассматриваемым блоком. Это будет очень похоже на управление памятью на простом языке c. Возможно, но чревато опасностью.

Удачи.

15
ответ дан 8 December 2019 в 02:35
поделиться

Зависит от того, что вы подразумеваете под «удаленным». Если их нет в интеллектуальном указателе и не удаляются явно, они не удаляются. Члены, которые являются просто частью класса:

class Bar {
//...
private: 
  Foo foo;
};

Не удаляются деструктором (потому что они не выделялись динамически), они просто уничтожаются. Они «живут» внутри класса, поэтому, как только он будет уничтожен, он исчезнет.

Если вы ищете долю «владения» между двумя местоположениями, вам нужен динамически выделяемый shared_ptr:

#include <memory>
class Bar {
// ...
private:
  std::tr1::shared_ptr<Foo> foo;
};
10
ответ дан 8 December 2019 в 02:35
поделиться

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

Если вместо этого ваш объект-контейнер косвенно ссылается на него (например, с помощью указателя), вам не нужно делать ничего, в частности, чтобы , а не его удалить. Деструктор ничего не удаляет, если вы явно не напишите для этого код.

Что касается вопроса о том, необоснованно ли это, я думаю, что в целом это не так, но вы должны пояснить (обычно в документации, поскольку C ++ не имеет языковой поддержки для этой концепции) какой объект владеет рассматриваемым членом.

2
ответ дан 8 December 2019 в 02:35
поделиться

Код в деструкторе предназначен только для удаления динамически выделяемых элементов. Уничтожение членов не является необязательным, вы можете контролировать только освобождение того, что вы явно выделили ранее (с помощью оператора new).

То, что вы хотите сделать, можно получить с помощью shared_ptr, в котором и ваш класс, и внешний код совместно использовать указатель на один и тот же внешний объект. Таким образом, он будет удален только тогда, когда все указатели на этот объект выйдут за пределы области видимости. Но будьте осторожны, чтобы не делать циклических ссылок, shared_ptr не имеет мудрости «сборщика мусора».

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

3
ответ дан 8 December 2019 в 02:35
поделиться

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

1
ответ дан 8 December 2019 в 02:35
поделиться

Если член содержится в значении (не указателем или ссылкой), то вы не можете предотвратить его удаление и не должны этого делать.

Если вместо этого вы хотите удалить его в другом месте, сделайте его содержащимся указателем или ссылкой.

class House
{
  Door door; //contained by value, will be destroyed when the House is
}

class House
{
  Door& door; //contained by reference, will not be destroyed when the House is
}
4
ответ дан 8 December 2019 в 02:35
поделиться

Прежде всего, это полностью неразумно?

Я бы не сказал, что это неразумно, возможно, сомнительно.

Совершенно допустимо, чтобы один класс владел и, следовательно, должен был позаботиться об очистке, имея в то же время ссылку или указатель на этот объект в другой класс.

Однако может возникнуть сомнение, должен ли второй класс иметь этот указатель или нет, я бы предпочел всегда использовать метод get для извлечения этого указателя всякий раз, когда он мне нужен, например, путем вызова родительского класса или какой-нибудь менеджер ресурсов.

0
ответ дан 8 December 2019 в 02:35
поделиться

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


class Foo
{
public:
  Foo() {p = new int;}
 ~Foo(){}

private:
 int a;
 int *p;
};

Этот класс имеет 2 члена данных: целое число a и указатель на целое число p . Когда вызывается деструктор, объект уничтожается, что означает, что вызываются деструкторы для всех его членов. Это происходит, даже если тело деструктора пусто. В случае примитивного типа, такого как целое число, вызов его деструктора просто означает, что память, которую он занимает, будет освобождена. Однако при уничтожении указателя есть загвоздка: все, на что он указывает, по умолчанию не уничтожается. Для этого вы должны явно вызвать delete .

Итак, в нашем примере a будет уничтожен при вызове деструктора, как и p , но не то, на что указывает p . Если вы хотите освободить память, на которую указывает p , деструктор для Foo должен выглядеть так:


~Foo() {delete p};

Итак, возвращаясь к вашему вопросу, все члены вашего класса которые не являются указателями, будут уничтожены, несмотря ни на что, при вызове деструктора объекта. С другой стороны, если у вас есть члены, которые являются указателями, все, на что они указывают, не будет уничтожено, если вы специально не вызовете для них delete в деструкторе.

0
ответ дан 8 December 2019 в 02:35
поделиться

Если у вас есть динамически выделенная память для этого члена, это возможно после того, как вы предоставили ссылку на этот член перед уничтожением объекта, и если вы убедитесь, что член не уничтожен в деструкторе объекта. Однако я думаю, что такая практика не столь разумна.

0
ответ дан 8 December 2019 в 02:35
поделиться

Почему никто не упомянул слабые и сильные указатели?
Сильный указатель - это умный указатель, который действует нормально.
Слабый указатель - это интеллектуальный указатель, который не может удалить себя, если все сильные указатели не находятся за пределами области действия.
Сильный указатель указывает на владение, слабый указатель указывает на совместное использование.
Посмотрите на boost.shared_ptr и boost.weak_ptr и StrongPtr Локи для реализации.
Также обратите внимание на RAII . Если бы вы знали RAII, вы бы сами знали ответ на этот вопрос.

0
ответ дан 8 December 2019 в 02:35
поделиться

Это небезосновательно, но следует позаботиться о том, чтобы очистка любых управляемых ресурсов выполнялась неявно.

(Первый управляемый ресурс, о котором обычно беспокоятся люди, - это память, но все, что угодно которые могут протекать - память, дескрипторы файлов, указатели IDispatch - должны иметь код, который неявно обрабатывает очистку).

Для управляемых ресурсов, совместно используемых несколькими объектами (почти наверняка, если «этот объект» должен иметь указатель на что-то который очищается «этим объектом»), вам обычно требуется либо «указатель с подсчетом ссылок» для управления объектом, либо «слабый указатель», в зависимости от требований вашего срока службы.

Для управляемых ресурсов, которые не используются совместно ( и, в частности, те, которыми нужно правильно управлять, когда могут быть выброшены исключения),тогда auto_ptr или другой вариант может быть более подходящим.

Книги Скотта Мейерса по эффективному C ++ были разумной отправной точкой для изучения интеллектуальных указателей, но на практике вам, вероятно, следует просто взять проверенную библиотеку, такую ​​как Boost и пусть кто-то другой позаботится о том, чтобы получить неясные угловые случаи (например, что произойдет, если конструктор выдает исключение?) правильно.

0
ответ дан 8 December 2019 в 02:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: