为什么继承不增加大小,但成员呢?

orl*_*rlp 1 c++ inheritance member

看看这三个类(包括ommited):

template<class T> struct A {
    std::allocator<T> allocator;
    T* ptr;
};

template<class T> struct B {
    T* ptr;
    std::allocator<T> allocator;
};

template<class T> struct C : std::allocator<T> {
    T* ptr;
};

int main(int argc, char **argv) {
    std::cout << "A: " << sizeof(A<int>) << "\n";
    std::cout << "B: " << sizeof(B<int>) << "\n";
    std::cout << "C: " << sizeof(C<int>) << "\n";
}
Run Code Online (Sandbox Code Playgroud)

如果你问我,取决于对齐方式,无论是AB有可能产生大小相同的作为C.但是,sizeof否则打印声明:

A: 16
B: 16
C: 8
Run Code Online (Sandbox Code Playgroud)

为什么会这样?

Ker*_* SB 5

通过C++ 11,9/4:

类类型的完整对象和成员子对象应具有非零大小.

没有这样的限制适用于基类,只要每一个对象具有唯一的一对类型和地址的.因此,只要"第一"数据成员没有与基础子对象相同的类型,基础子对象可以具有零大小,既不完整也不是成员.

(我将"第一个"放在引号中,因为存在涉及访问级别的复杂性.)

事实上,1.8/5-6正式化了上述内容:

5除非它是一个位域(9.6),否则一个派生最多的对象应具有非零大小,并且应占用一个或多个存储字节.基类子对象可以具有零大小.平凡可复制或标准布局类型(3.9)的对象应占用连续的存储字节.

6除非对象是零字段或零大小的基类子对象,否则该对象的地址是它占用的第一个字节的地址.如果一个是另一个的子对象,或者如果至少一个是零大小的基类子对象并且它们是不同类型的,则不是位字段的两个对象可以具有相同的地址; 否则,他们应有不同的地址.


这是一个"典型"实现std::vector,减去所有名称修改:

template <typename T, typename Alloc>
class vector
{
    struct vbase : Alloc
    {
        T * data, * end, * capacity;
        vbase(Alloc const & a) : Alloc(a), data(), end(), capacity() { }
    };

    vbase impl;

public:
    vector(Alloc const & a = Alloc()) : impl(a) { }

    T * data() const { return impl.data; }
    T & operator[](size_t n) { return data()[n]; }

    // ...

    // use impl.allocate(), impl.construct() etc.
};
Run Code Online (Sandbox Code Playgroud)

这基本上确保了sizeof(vector<T>) == 3 * sizeof(T*)每当分配器为空时.