在非多态继承中是否存在性能/内存使用影响?

时间:2016-06-21 10:30:28

标签: c++ c++11 inheritance smart-pointers

我很好奇非多态类中继承的影响。具体来说,我正在编写两个智能指针类,既不使用虚方法,也是为了非常独特的目的。由于基本运算符重载并且某些标准函数是相同的,并且它们只需要一个成员变量,我想我可以使用基类来重用代码。这是我的意思的简单模型

基类:

template <class T>
class Pointer_Impl
{
public:
    T & operator*() { return this->*m_pointer; }
    // etc.
protected:
    T *m_pointer;
    //protected to prevent instantiation without using = delete
    Pointer_Impl() {}
    Pointer_Impl(T *) {}
    //other constructors, assignment and move operators, destructor here
};

然后:

template <class T>
class PointerA : public Pointer_Impl<T>
{
public:
    PointerA() { m_pointer = nullptr; }
    PointerA(T * obj) { m_pointer = obj; }
    // other constructors, assignment and move operators, destructor, and any other class-specific functions here
};

问题:从缺少任何虚拟方法的基类派生的内存或性能是否有任何开销?由于它是一个智能指针实现,精益和平均是我正在寻找的。

我的直觉说不,没有任何顾虑,但我想从更聪明的头脑中确定。

3 个答案:

答案 0 :(得分:7)

绩效影响

无。如果没有virtual(虚拟继承或虚函数),您将不会因使用基类而受到任何运行时处罚。名称解析完全在编译时使用静态类型执行。

内存影响

无。在没有virtual的情况下,继承的类和直接与成员具有相同字段的类之间没有任何有意义的区别。如果您有多个基类或virtual(继承或函数),则会发生这一切。

编译影响

编制时间可能会有一些影响;编译器必须跟踪更多的名称和模板实例。对于大型,模板密集的代码库来说,有时是一个问题。

答案 1 :(得分:5)

您的子类的构造函数表明该子类至少包含一个您未显示的其他成员m_object

没有任何虚方法,在运行时,由超类和子类组成的对象与由单个类组成的对象(具有典型的C ++实现)之间没有区别。毕竟,创建子类最终会创建一个新类。因此,包含基类的所有成员和子类的单个类在运行时与单个类无法区分,只要所有类成员相同,按相同顺序排列,并且不涉及虚拟继承。

当然,编译器必须做更多的工作来跟踪超类和子类,所以编译器必须做一些额外的工作,跟踪两个单独的类,而不是一个。但是,除非代码库很大,否则我怀疑性能的差异是可以衡量的。

答案 2 :(得分:4)

没有任何类型的运行时性能损失(如果优化。显然,调试版本可能存储一些有关继承的数据)。

作为证据,请遵守以下程序的输出

PROG1:

template <class T>
class PointerA
{
public:
    PointerA(T * obj) : m_pointer(obj) {}
    T & operator*() { return *this->m_pointer; }
    T *m_pointer;
};

PROG2:

template <class T>
class Pointer_Impl
{
public:
    T & operator*() { return *this->m_pointer; }
protected:
    T *m_pointer;
    Pointer_Impl(T *) {}
};

template <class T>
class PointerA : public Pointer_Impl<T>
{
public:
    PointerA(T * obj) : Pointer_Impl<T>(obj) {}
};

共同主要:

int main() {
    PointerA<int> p(new int);
    volatile int i = 42;
    *p = i;
    i = *p;
}

两者都产生相同的组件:

main:
        subq    $24, %rsp
        movl    $4, %edi
        call    operator new(unsigned long)
        movl    $42, 12(%rsp)
        movl    12(%rsp), %eax
        movl    %eax, 12(%rsp)
        movl    $0, %eax
        addq    $24, %rsp
        ret