Modern C++ sizeof(std::tuple)的秘密及实现代码解读

本文深入探讨了C++中std::tuple的sizeof特性,通过类继承与has-a关系的对比,揭示了std::tuple如何利用空类优化节省空间。文章通过实例分析了std::tuple在包含空类和非空类对象时的内存布局,并介绍了编译器在处理继承和对象持有时的优化策略。同时,提到了Windows下的__declspec(empty_bases)属性用于空基类优化。
摘要由CSDN通过智能技术生成

1. 前言

我们曾经至少四篇帖子或多或少的提到过std::tuple的原理及占用空间大小:

  1. Modern C++ std::unique_ptr的实现原理
  2. Modern C++ std::tuple的size
  3. Modern C++利用工具快速理解std::tuple的实现原理
  4. GDB调试技巧实战–自动化画出类关系图

但是,当初在第一篇中提出的size的问题还悬而未决,今天我将着重讲这一块,同时也会讲一些tuple的实现代码。

2. 类继承 VS 类has-a

2.1 一般继承与有一个父对象

考虑下面的两片代码:

struct Base {
   
	int i;
}; 
 
struct Derived1 : Base
{
   
    int j;
};
struct Base {
   
	int i;
}; 
 
struct Derived1
{
   
	Base b;
    int j;
};

本质上没有什么区别,第一种是继承Base, 也相当于has a Base。它们的sizeof大小也相同。
加强训练下,猜下下面的程序的输出???:

#include<iostream>
#include <tuple>
using namespace std;


struct Base {
   
	int i;
}; // empty class

struct Derived1 : Base
{
   
    int i;
};

struct Derived2 : Base
{
   
    int i;
};

struct Derived3 : Derived2, Derived1
{
   
};

int main()
{
   
	Derived3 d;
	std::cout<<sizeof(d)<<std::endl;
}

我没有给初始化,所以i的值比较随机,这反而能看出我们真的有4个i, 特别是Base.i有两个:

(gdb) p d
$1 = {
   <Derived2> = {
   <Base> = {
   i = -10544}, i = 32767}, <Derived1> = {
   <Base> = {
   i = 0}, i = 0}, <No data fields>}

2.2 继承空类 VS 有一个空类对象

但是,如果把Base换成空类哪?如果没有优化,第一种情况还相当于has a Base其大小是1,加上一个int总共8字节(有对其)。但历史没有假设,标准还偏偏允许有优化:Empty base optimization
继承的情况大小为4字节,比has a情况少用4个字节!

2.3 std::tuple中放空类对象 – 继承空类

一言以蔽之:std::tuple正是用了继承而非has a 而节约的空间。
我们举个例子,就举《Modern C++ std::unique_ptr的实现原理》中的例子吧,std::unique_ptr的本质是std::tuple<int*, std::default_delete>, 它的大小是指针的大小8,而不是16. 写个程序验证一下:

#include<iostream>
#include <tuple>
#include <memory>
using namespace std;

int main()
{
   
	int i=5;
	std::tuple<int*
  • 29
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

深山老宅

鸡蛋不错的话,要不要激励下母鸡

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值