设为首页 加入收藏

TOP

C++对象模型:g++的实现(一)(一)
2023-07-23 13:33:10 】 浏览:79
Tags:

刚看完了《深度探索C++对象模型》第三章,这里做一下总结,也写一下我自己在g++ 7.5.0上的验证。
本文中所有的源文件都可以在这里拿到(百度网盘链接)。
注意,这里所说的“对象”是指在C++中使用classstruct关键字创建的类的实例。

1. 无继承情况下的C++对象内存布局

首先当然是从最基础的情况来讲,在没有继承的情况下的C++对象内存布局是什么样的?这又分为两种:无虚函数和有虚函数。

1.1 无虚函数

C++类内成员变量分为两类:static成员变量和非static成员变量。static成员变量不在类的实例的内部,在整个内存中只有一份,只需要使用类名即可访问;而非static成员变量在类的实例内部,需要为其分配空间。
在这种情况下C++的对象和C的结构体是一样的,毕竟要实现和C的兼容,主要就是结构体/类内成员变量的对齐。
其一般规则总结如下:

  1. 所有成员按照在类内的声明顺序在内存中排列;
// test00.cpp
#include <iostream>

int main();

class Test00 {
    friend int main();
public:
    int i1;
private:
    int i2;
public:
    int i3;
};

#define showOffset(ClassName, memberName) (reinterpret_cast<unsigned long>( &(static_cast<ClassName*>(nullptr)->memberName)))

int main() {
    std::cout << showOffset(Test00, i1) << std::endl;
    std::cout << showOffset(Test00, i2) << std::endl;
    std::cout << showOffset(Test00, i3) << std::endl;
}

// Output:
//  0
//  4
//  8
  1. 任一非static成员变量的偏移(offset)要是其大小的倍数;
// test01.cpp
#include <iostream>
struct Test01 {
    char c;
    int i; // 如果紧凑排列,则i的偏移为1,但i的size为4,偏移要是4的倍数,因此i的偏移为4
};

#define showOffset(ClassName, memberName) (reinterpret_cast<unsigned long>( &(static_cast<ClassName*>(nullptr)->memberName)))

int main() {
    std::cout << showOffset(struct Test01, i) << std::endl;
}

// Output:
//  4
  1. 结构体整体的size需要为最大非static成员变量size的倍数;
// test02.cpp
#include <iostream>

// 如果紧凑排,Test02_1的size应为9,
// 但要与int(size为4)对其,所以其size为12
struct Test02_1 {
    char c1;  // Offset: 0
    int i;    // Offset: 4
    char c2;  // Offset: 8
};

// Test02_2成员和Test02_1相同,但顺序不同,
// 受规则2和3影响,其size为8
struct Test02_2 {
    char c1;  // Offset: 0
    char c2;  // Offset: 1
    int i;    // Offset: 4
};

int main() {
    std::cout << "sizeof Test02_1: " << sizeof(Test02_1) << std::endl;
    std::cout << "sizeof Test02_2: " << sizeof(Test02_2) << std::endl;
}

// Output:
//  sizeof Test02_1: 12
//  sizeof Test02_2: 8
  1. 空对象的size为1,为了保证每个对象都有唯一的内存位置(memory location)
// test03.cpp
#include <iostream>

struct Test03 {}; // Empty class

int main() {
    Test03 a, b;
    std::cout << "sizeof Test03: " << sizeof(Test03) << std::endl;
    if (&a == &b)
        std::cerr << " Error! &a == &b, at " << static_cast<void*>(&a) <<  std::endl;
    else
        std::cout << "a and b has different address, &a = " << static_cast<void*>(&a) << " and &b = " << static_cast<void*>(&b) << std::endl;
}

// Output:
//  sizeof Test03: 1
//  a and b has different address, &a = 0x7fffe62e8486 and &b = 0x7fffe62e8487
  1. 当类(class)/结构体(struct) A 作为一个类B的内部成员变量时,其对齐要求为类A内部最大的对齐要求;
// test04.cpp
#include <iostream>

// 规则2中的类,size为8,对齐要求为4
struct Test01{
    char c;
    int i;
};

struct Test04 {
    char c;   // Offset: 1, size 1
    Test01 t; // Offset: 4, size 8
};

#define showOffset(ClassName, memberName) (reinterpret_cast<unsigned long>( &(static_cast<ClassName*>(nullptr)->memberName)))

int main() {
    std::cout << "Offset of t in struct Test04: " << showOffset(Test04, t) << std::endl;
    std::cout << "sizeof Test04: " << size
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇c++对象模型 模板 异常处理 执行.. 下一篇C++对象模型:g++实现(二)

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目