编译器在 GCC 和 MSVC 中生成析构函数和警告

Compiler generated destructors and warnings in GCC and MSVC

我正在努力清除一些在使用提升警告时同时出现在 GCC 和 MSVC 上的警告。我在 MSVC 下捕获了一个 "class has virtual functions, but destructor is not virtual instances of this class may not be destructed correctly"。当启用适当的警告时,我在 GCC 和 Clang 下收到类似的警告。我正在尝试了解投诉内容。

有问题的 class 有 no 析构函数(虚拟或其他;由人类编写)。它的基础classes也是如此。 class 有堆栈分配的成员对象,但 new 没有分配任何成员对象。 class 是 template。最后,有时,层次结构中的 classes 被标记为 "no vtable"(但这不是这种情况)。

如果我添加一个空的虚拟析构函数,则警告被清除。但我想确保我没有遗漏一些不明显的东西,因为上面有一些限制。

以下是我遇到的与编译器相关的问题和警告:

如果上面的答案有效 "I need to learn to work with my tools",那么我很乐意提供空的 dtor 来使用分析工具。 (我认为声称这些工具不如程序员聪明是非常虚伪的,所以禁用它们。坏人可能一路笑到银行,摘下开发人员不会被打扰的低垂果实......) .


这是带有警告标记的 classes 之一。

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
};

以下是一些相关问题:

The class in question has no destructor (virtual or otherwise).

有趣的事实:C++ 中的所有对象都有一个析构函数。很简单,如果你不定义一个,编译器会生成它,对于原语,这是一个空操作。

Why is the compiler generated destructor not virtual?

因为人们抱怨如果每个 C++ 程序中的每个 class 都有一个虚拟析构函数,会对他们的性能产生不利影响。

Why is the compiler generated destructor not sufficient?

它完全足够 - 用于销毁它为之生成的 class。销毁它的派生 classes,如果有的话,是它不应该服务的目的。

What is the difference between an empty dtor provided by me and a default dtor provided by the compiler?

如果您没有将其定义为 virtual,那么空的 dtor 将禁止优化(有时),仅此而已。否则,区别很明显——你的是 virtual(另外)。某些模板可能要求您的 class 可以轻易破坏,但这并不常见。

Does templates affect what the compiler can generate?

没有

Does "no vtable" affect what the compiler can generate?

没有

编译器生成的析构函数不是虚拟的,除非 class 有一个带有虚拟析构函数的基。

原因是 "zero overhead if not used" 规则 - 虚函数引入了成本,除非有某种原因使析构函数为虚函数(例如,基类具有虚析构函数,或者程序员声明了一个)析构函数不会是虚拟的。

编译器提供的空析构函数与程序员提供的析构函数之间没有区别,除非编译器生成的编译器是非虚拟的并且程序员将析构函数声明为虚拟的。

由于模板是一种编译时机制,它们会影响编译器生成和可以生成的内容。这个问题太笼统,无法更具体地回答。

你的最后一个问题是特定于编译器的。一般来说,对于使用 vtables 的编译器,没有 vtable 的 class 不能有虚函数,并且 - 如果 class 将任何函数声明为虚函数或者它继承自具有任何虚函数的 class函数 - 它将获得一个 vtable。在某些情况下(多重继承)class 可能有多个 vtables。