I'm working on clearing some warnings that show up on both GCC and MSVC when elevated warnings are in use. I'm catching a "class has virtual functions, but destructor is not virtual instances of this class may not be destructed correctly" under MSVC. I get a similar warning under GCC and Clang when the appropriate warnings are enabled. I'm trying to understand what the complaint is.
The class in question has no destructor (virtual or otherwise; authored by humans). The same is true of its base classes. The class has stack allocated member objects, but nothing allocated with new
. The class is a template
. And finally, sometimes, the classes in the hierarchy are marked as "no vtable" (but this is not this case).
If I add an empty virtual destructor, then the warning is cleared. But I want to make sure I'm not missing something non-obvious given some of the constraints above.
Here are the questions I have related to the compiler and the warnings:
If the answers above are effectively "I need to learn to work with my tools", then I'm happy to provide empty dtors to work with the analysis tools. (I think its very disingenuous to claim the tools aren't as smart as the programmer, so disable them. The bad guys probably laugh all the way to the bank picking the low hanging fruit the developer could not be bothered with...).
Here's one of the classes that gets tagged with the warning.
template <class T>
class DL_FixedBasePrecomputationImpl : public DL_FixedBasePrecomputation<T>
{
public:
typedef T Element;
DL_FixedBasePrecomputationImpl() : m_windowSize(0) {}
// DL_FixedBasePrecomputation
bool IsInitialized() const
{return !m_bases.empty();}
void SetBase(const DL_GroupPrecomputation<Element> &group, const Element &base);
const Element & GetBase(const DL_GroupPrecomputation<Element> &group) const
{return group.NeedConversions() ? m_base : m_bases[0];}
void Precompute(const DL_GroupPrecomputation<Element> &group, unsigned int maxExpBits, unsigned int storage);
void Load(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation);
void Save(const DL_GroupPrecomputation<Element> &group, BufferedTransformation &storedPrecomputation) const;
Element Exponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent) const;
Element CascadeExponentiate(const DL_GroupPrecomputation<Element> &group, const Integer &exponent, const DL_FixedBasePrecomputation<Element> &pc2, const Integer &exponent2) const;
private:
void PrepareCascade(const DL_GroupPrecomputation<Element> &group, std::vector<BaseAndExponent<Element> > &eb, const Integer &exponent) const;
Element m_base;
unsigned int m_windowSize;
Integer m_exponentBase; // what base to represent the exponent in
std::vector<Element> m_bases; // precalculated bases
};
Here are some related questions:
The class in question has no destructor (virtual or otherwise).
Fun fact: All objects in C++ have a destructor. It's simply that if you don't define one, the compiler generates it, and for primitives, it's a no-op.
Why is the compiler generated destructor not virtual?
Because people complained that it would adversely affect their performances if every single class in every C++ program had a virtual destructor.
Why is the compiler generated destructor not sufficient?
It's perfectly sufficient- for destroying the class it's generated for. Destroying it's derived classes, if any, is a purpose it's not supposed to serve.
What is the difference between an empty dtor provided by me and a default dtor provided by the compiler?
If you didn't define it as virtual
, then the empty dtor will prohibit optimizations (sometimes) and that's it. Otherwise, the difference is obvious- yours is virtual
(in addition). Some templates may require that your class is trivially destructible but it's not common.
Does templates affect what the compiler can generate?
No.
Does "no vtable" affect what the compiler can generate?
No.