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

时间:2015-06-29 08:59:45

标签: c++ visual-c++ gcc warnings virtual-destructor

我正在努力清除在使用提升警告时出现在GCC和MSVC上的一些警告。我正在捕捉一个“类有虚函数,但析构函数不是这个类的虚拟实例可能无法正确破坏”在MSVC下。当启用适当的警告时,我在GCC和Clang下会收到类似的警告。我想知道投诉是什么。

相关课程有 析构函数(虚拟或其他;由人类创作)。其基类也是如此。该类具有堆栈分配的成员对象,但没有分配new。该课程为template。最后,有时,层次结构中的类被标记为“no vtable”(但这不是这种情况)。

如果我添加一个空虚拟析构函数,则清除警告。但是我想确保在不考虑上述一些限制的情况下,我不会遗漏一些不明显的东西。

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

  • 为什么编译器生成的析构函数不是虚拟的?
  • 为什么编译器生成的析构函数不够用?
  • 由我提供的空dtor与编译器提供的默认dtor有什么区别?
  • 模板是否影响编译器可以生成的内容?
  • “no vtable”是否影响编译器可以生成的内容?

如果上面的答案实际上是“我需要学习使用我的工具”,那么我很乐意提供空的dtors来使用分析工具。 (我认为声称这些工具并不像程序员那样聪明,所以要禁用它们。坏人可能会一直笑到银行选择开发人员无法解决的低成果......)

这是一个被警告标记的类。

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

以下是一些相关问题:

2 个答案:

答案 0 :(得分:3)

  

有问题的类没有析构函数(虚拟或其他)。

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

  

为什么编译器生成的析构函数不是虚拟的?

因为如果每个C ++程序中的每个类都有一个虚拟析构函数,人们会抱怨它会对他们的表现产生负面影响。

  

为什么编译器生成的析构函数不够?

完全足以破坏它所生成的类。如果有的话,摧毁它的派生类就是它不应该服务的目的。

  

我提供的空dtor和a之间有什么区别   默认dtor由编译器提供?

如果你没有将它定义为virtual,那么空的dtor将禁止优化(有时),就是这样。否则,差别很明显 - 你的是virtual(另外)。有些模板可能要求您的课程可以轻易破坏,但这并不常见。

  

模板是否影响编译器可以生成的内容?

没有

  

“没有vtable”会影响编译器可以生成什么吗?

没有

答案 1 :(得分:1)

编译器生成的析构函数不是虚拟的,除非该类具有带虚拟析构函数的基础。

原因是“零开销,如果不使用”规则 - 虚函数引入了成本,除非有一些理由使析构函数是虚拟的(例如,一个基础有一个虚拟析构函数,或程序员声明一个)析构函数不会是虚拟的。

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

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

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