Деструктор класса, неявно определенного
Рассмотрим случай класса, который не имеет destructor
а также constructor
явно заявлено разработчиком. Я понимаю что destructor
для класса будет implicitly declared
в этом случае. Тогда правда ли, что destructor
является implicitly defined
, только когда объект класса собирается быть уничтоженным?
Поведение конструктора также такое же, как указано выше. Это implicitly defined
только когда объект класса создан?
РЕДАКТИРОВАТЬ
class A {
public:
};
int main() {
}
В приведенном выше коде ~A() будет объявлено неявно. Мой вопрос заключается в том, правда ли, что определение деструктора будет сделано неявно, только если объект класса создан как
class A {
public:
};
int main() {
A a;
}
Или это неявно определяется, даже если создание объекта не сделано?
3 ответа
Да, неявно объявленные конструкторы и деструкторы по умолчанию неявно определяются, когда они используются для создания или уничтожения экземпляров объекта. В словах стандарта (C++ 11):
12.1 / 6: Конструктор по умолчанию, который по умолчанию и не определен как удаленный, неявно определяется, когда он используется odr (3.2) для создания объекта своего типа (1.8) или когда он явно дефолтен после его первого объявления.
12.4 / 5: деструктор, который по умолчанию и не определен как удаленный, неявно определяется, когда он используется odr (3.2) для уничтожения объекта своего типа класса (3.7) или когда он явно дефолтен после его первого объявления.
Таким образом, они определены в вашем втором фрагменте кода, который создает и уничтожает объект типа A
, но не в первом, чего нет.
С одной стороны, зачастую невозможно решить, был ли когда-либо создан / уничтожен объект в любой нетривиальной программе *, с другой стороны, это не имеет большого значения, пока наблюдаемое поведение остается тем же.
Тем не менее, есть тонкая грань между defined when object created/destroyed
, а также defined if needed
, В моем примере ниже, Foo::Foo()
должно быть определено, потому что есть потенциал для этого. Однако вы спрашиваете, определен ли он при создании объекта, и последний не является разрешимым.
*:
class Foo {};
int main(int argc, char *argv[]) {
if (argc>1) Foo(); // <- impossible to decide if ever constructed/destroyed
}
// On the other hand, compiler might be smart enough to observe that
// Foo does not have any visible behaviour, remove Foo entirely, and in
// effect spit out this:
int main() {}
То, определена ли функция, не является чем-то, что определяется во время выполнения, поэтому деструктор не может быть " определен, только когда объект [..] собирается быть уничтоженным " просто потому, что ваш исполняемый файл статичен и не создан для определенного запуска.
Однако, если в конечном исполняемом файле нет вызовов вашему деструктору, компоновщик мог бы вообще удалить эту функцию.
Для последнего пункта рассмотрим этот пример:
class A {
A() {}
~A() {}
};
class B {
A a; // cannot access dtor nor ctor of A
};
Если вы никогда не создаете экземпляр B
это будет на самом деле скомпилировать и связать, потому что нет B::B()
и нет B::~B()
когда-либо синтезируется. Однако, если вы попытаетесь создать объект B
компилятор назовет вас красочными именами просто потому, что вы заставили его синтезировать B::B()
а также B::~B()
что он не может сделать.