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)
如果你问我,取决于对齐方式,无论是A或B有可能产生大小相同的作为C.但是,sizeof否则打印声明:
A: 16
B: 16
C: 8
Run Code Online (Sandbox Code Playgroud)
为什么会这样?
通过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*)每当分配器为空时.