Russian Qt Forum

Qt => Общие вопросы => Тема начата: alexis031182 от Июнь 21, 2012, 20:13



Название: [РЕШЕНО] Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 21, 2012, 20:13
Предположим, есть классы:
Код
C++ (Qt)
class Base {
  Base() {}
  virtual ~Base() {}
};
 
class A : public Base {};
class B : public Base {};
//... и т.д.
 
В Интернете, находясь в поиске решения очередной задачи, не раз замечал предложения виртуальный деструктор базового класса делать чисто виртуальным. Но нет, я не про тот случай, когда указанный метод применяют для превращения класса в абстрактный при отсутствии других виртуальных методов. Пишут, что работает быстрее следующее:
Код
C++ (Qt)
class Base {
  Base() {}
  virtual ~Base() = 0;
};
 
inline Base::~Base() {}
 
Объясните, почему так? Понимаю, что разница в скорости если и есть, то не шибко большая. Но вопрос принципиален. Спасибо.


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Alex Custov от Июнь 21, 2012, 21:07
быстрее настолько, насколько увеличится скорость за счёт inline, которого может и не быть по усмотрению компилятора. Короче, сомнительно. Единственное что я вижу - если в классе нет других чистых виртуальных методов, то запретить создавать объекты этого класса за счёт деструктора.


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 21, 2012, 21:12
быстрее настолько, насколько увеличится скорость за счёт inline, которого может и не быть по усмотрению компилятора. Короче, сомнительно.
Вот и я не понимаю, с чего это будет работать быстрее.

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


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Blackwanderer от Июнь 22, 2012, 10:43
Все методы, определённые внутри объявления класса по умолчанию считаются inline методами.


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Wlad_C от Июнь 22, 2012, 14:41
Цитировать
Пишут, что работает быстрее ...
Виртуальные методы выполняются медленней не виртуальных, т.к. обращение к ним происходит не напрямую а через таблицы, которые создает компилятор.
Поэтому скорость здесь не причем (она будет медленней). А деструкторы должны быть виртуальными потому, что в спецификации С++ постулируется, что когда объект производного класса уничтожается через указатель на базовый класс с не виртуальным деструктором, то результат не определен. То есть, объекты принадлежащие производному классы могут быть не удалены.


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: mutineer от Июнь 22, 2012, 15:01
простите, а что значит "уничтожается через указатель на базовый класс"??

Код:
Base *ptr = new Derived();
...
delete ptr;


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 22, 2012, 15:04
Мой вопрос несколько об ином. Из двух вариантов виртуальных деструкторов пишут, что один будет быстрее, другой медленнее. Почему? Есть ли вообще основания считать означенное утверждение верным? Вопрос именно в этом. Может оно конечно бабка надвое сказала, но тем не менее мне интересно.


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: OKTA от Июнь 22, 2012, 15:14
я вот нашел седующее:
1. inline методы вставляются компилятором везде, где вызываются - соответственно скорость выше (но вставляются или нет - точно неизвестно, т.к. это рекомендации для компилятора)
2. если дектсруктор виртуальный, то при уничтожении класса вызовется его деструктор и деструктор базового класса, а если не виртуальный, то деструктор только базового класса!

Соответственно выводы делаются!


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 22, 2012, 15:19
Повторюсь. Речь не о виртуальности, не инлайне как таковом, и не о правилах вызова деструкторов.

Вот нашёл одно из мест, где видел (http://www.parashift.com/c++-faq-lite/pointers-to-members.html#faq-33.13) указанное в теме утверждение.
Цитировать
With functionoids, you first create a base class with a pure-virtual method:
Код
C++ (Qt)
class Funct {
public:
  virtual int doit(int x) = 0;
  virtual ~Funct() = 0;
};
 
inline Funct::~Funct() {}  // defined even though it's pure virtual; it's faster this way; trust me


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Igors от Июнь 22, 2012, 15:44
Конечно приятно позаниматься взвешиванием "на аптекарских весах", типа "оптимизация с до упора" - работа эксперта :) А соседняя строчка напр
Код
C++ (Qt)
QString s("text");
 
Ой сколько экономий на деструкторе она перекроет! Но ей заниматься почему-то не хочется.. Нет вдохновения, да и вообще возиться с собственным строчником - фу, какая пошлость..  :)



Название: Re: Виртуальный деструктор: чисто или не чист
Отправлено: mutineer от Июнь 22, 2012, 15:47
Конечно приятно позаниматься взвешиванием "на аптекарских весах", типа "оптимизация с до упора" - работа эксперта :) А соседняя строчка напр
Код
C++ (Qt)
QString s("text");
 
Ой сколько экономий на деструкторе она перекроет! Но ей заниматься почему-то не хочется.. Нет вдохновения, да и вообще возиться с собственным строчником - фу, какая пошлость..  :)

Так а каков ответ на вопрос "почему оно быстрее?"


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: OKTA от Июнь 22, 2012, 15:54
в ссылке тип написал, чтобы ему верили, что работает быстрее))) думаю по этой причине и быстрее))))


Название: Re: Виртуальный деструктор: чисто или не чист
Отправлено: Blackwanderer от Июнь 22, 2012, 15:54
Так а каков ответ на вопрос "почему оно быстрее?"
Да не будет оно быстрее!!! Нет, возможно когда-то давно, когда трава была зеленее, небо голубее, а программисты умнее компиляторов это все имело смысл, а сейчас... Сейчас две эти конструкции абсолютно эквивалентны.


Название: Re: Виртуальный деструктор: чисто или не чист
Отправлено: mutineer от Июнь 22, 2012, 15:57
Так а каков ответ на вопрос "почему оно быстрее?"
Да не будет оно быстрее!!! Нет, возможно когда-то давно, когда трава была зеленее, небо голубее, а программисты умнее компиляторов это все имело смысл, а сейчас... Сейчас две эти конструкции абсолютно эквивалентны.

Че так нервничать-то? Не быстрее, так не быстрее, это тоже ответ на вопрос:)


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 22, 2012, 16:02
Конечно приятно позаниматься взвешиванием "на аптекарских весах", типа "оптимизация с до упора" - работа эксперта :)
Причём здесь это? Я и говорил, что "бабка надвое сказала". Просто непонятна мне эта конструкция. А поскольку автор написал "доверься мне", это сподвигло меня на создание темы в форуме :)

А соседняя строчка напр
Код
C++ (Qt)
QString s("text");
 
Ой сколько экономий на деструкторе она перекроет! Но ей заниматься почему-то не хочется.. Нет вдохновения, да и вообще возиться с собственным строчником - фу, какая пошлость..  :)
И это тоже интересно :)


Название: Re: Виртуальный деструктор: чисто или не чист
Отправлено: alexis031182 от Июнь 22, 2012, 16:04
Че так нервничать-то? Не быстрее, так не быстрее, это тоже ответ на вопрос:)
++


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Fat-Zer от Июнь 22, 2012, 16:11
чего-то я отупел, а какая «медленная» альтернатива?
с раскоменченной строкой, само собой, всё нормально...
Код
C++ (Qt)
#include <iostream>
class Base {
public:
       Base() {}
       virtual ~Base() = 0;
};
// inline ~Base() {}
 
class Derived: Base {
public:
       Derived() {};
       virtual ~Derived() {
               std::cout << "Derived::~Derived\n";
       }
};
 
int main() {
       Derived d;
       return 0;
}

Код:
alexander@goblin /tmp $ g++ 1.cpp
/tmp/cc3mCBWm.o: In function `Derived::~Derived()':
1.cpp:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev]+0x2f): undefined reference to `Base::~Base()'
1.cpp:(.text._ZN7DerivedD2Ev[_ZN7DerivedD5Ev]+0x58): undefined reference to `Base::~Base()'
collect2: выполнение ld завершилось с кодом возврата 1
ЗЫ: и что быстрее, компиляция или скорость выполнения?


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: OKTA от Июнь 22, 2012, 16:17
Derived d();


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 22, 2012, 16:20
чего-то я отупел, а какая «медленная» альтернатива?
...
Код
C++ (Qt)
virtual ~Base() {}

ЗЫ: и что быстрее, компиляция или скорость выполнения?
Я так понимаю, что скорость выполнения. Если скорость компиляции, то не слишком интересно.


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Fat-Zer от Июнь 22, 2012, 16:51
Derived d();
мы же не функцию хотим объявить...

у меня показывает, что время примерно одинаково...
1.cpp
Код
C++ (Qt)
#include <iostream>
class Base {
public:
       Base() {}
       virtual ~Base() = 0;
};
 
inline Base::~Base() {}
 
class Derived: public Base {
public:
       Derived() {};
       virtual ~Derived() {}
};
 
int main() {
       int i=100500000;
       do {
               Derived d;
       } while(i--);
       return 0;
}
 
2.cpp
Код
C++ (Qt)
#include <iostream>
class Base {
public:
       Base() {}
       virtual ~Base() {}
};
 
class Derived: public Base {
public:
       Derived() {};
       void foo() {};
       virtual ~Derived() {}
};
 
int main() {
       int i=100500000;
       do {
               Derived d;
       } while(i--);
       return 0;
}
Код:
alexander@goblin /tmp $ g++ 1.cpp -O0 -o test1
alexander@goblin /tmp $ g++ 2.cpp -O0 -o test2
alexander@goblin /tmp $ time ./test1

real    0m22.259s
user    0m22.254s
sys     0m0.001s
alexander@goblin /tmp $ time ./test1

real    0m22.286s
user    0m22.280s
sys     0m0.001s
alexander@goblin /tmp $ time ./test2

real    0m22.312s
user    0m22.263s
sys     0m0.034s
alexander@goblin /tmp $ time ./test2

real    0m22.270s
user    0m22.264s
sys     0m0.001s
ЗЫ: спойлеров не хватает...


Название: Re: Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 22, 2012, 16:59
Спасибо, Fat-Zer :)

З.Ы. А всё-таки немножко жаль, что чуда нет


Название: Re: [РЕШЕНО] Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Bepec от Июнь 22, 2012, 18:14
Да уже давно было сказано, что inline является лишь рекомендацией и в принципе не способен уже (на нынешний момент) влиять на скорость. ;)

Компилятору начхать на эту строчку, его алгоритмы умнее нас с вами в области оптимизации inlin' ом :)


Название: Re: [РЕШЕНО] Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Авварон от Июнь 23, 2012, 15:52
Логично, что в пределах 1го файла будет одинаковая скорость - он и так инлайнится.

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

Это предположение похоже на правду, но нужно протестить всё равно.


Название: Re: [РЕШЕНО] Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: alexis031182 от Июнь 23, 2012, 15:56
Другими словами, если удалять через указатель на наследника?


Название: Re: [РЕШЕНО] Виртуальный деструктор: чисто или не чисто, вот в чём вопрос
Отправлено: Авварон от Июнь 23, 2012, 16:35
Нет, если создавать объект на стеке. При удалении наследника компилер не может знать - финальный ли это наследник в цепочке, или нет.