【问题标题】:Inlining struct member内联结构成员
【发布时间】:2020-12-01 07:34:35
【问题描述】:

我有一个结构体Foo,其中包含一个嵌套结构体Bar。这些结构仅包含 POD 类型。我的问题是Foo 的大小比我复制Bar 的所有成员时要大:

#include <iostream>
#include <string>

struct Bar {
    double a;
    long long b;
    int c;
};

struct Foo {
    Bar b;
    int d;
};

struct Foo2 {
    double a;
    long long b;
    int c;
    int d;
};

int main()
{
  std::cout << sizeof(Foo) << std::endl;
  std::cout << sizeof(Bar) << std::endl;
  std::cout << sizeof(Foo2) << std::endl;
}

32 24 24

Demo

我知道这是因为 Bar 被填充到 24 个字节,所以 Foo 添加了一个 int 然后被填充到 32 个字节。我不想将BarFoo 标记为已打包。我想知道是否有任何方法可以告诉编译器不要将 Bar 存储为结构,而只包含其成员?比如:

struct Foo {
    inline Bar b; // Keyword inline doesn't work here.
    int d;
};

【问题讨论】:

  • I don't want to mark Bar or Foo as packed. 为什么不呢?
  • @eerorika 可能会降低性能?
  • 几个原因: 1. 它使代码的可读性降低 2. 它可能会降低性能 3. Bar 来自外部库,所以我无法修改它。 4. 不确定它的便携性。
  • @TonyTannous OP 试图只用填充重叠成员,而不是使成员错位。
  • 您能否解释一下为什么这对您来说是个问题。填充可能会因使用的编译器、版本和编译器标志以及成员本身的使用方式而异。所以你实际上不能保证Foo2Foo 具有相同的对齐方式。

标签: c++ struct


【解决方案1】:

我们必须允许成员成为可能重叠的子对象。有两种方法:1. 不使用成员,而是从Bar 继承或 2. 使用属性[[no_unique_address]] (C++20)。

从技术上讲,潜在的重叠足以让编译器重新使用填充。然而,不幸的是,能够重用填充并不能保证重用,并且在实践中,某些语言实现不会重用可简单复制的标准布局类型的填充。我们可以通过使子对象不可复制或非标准布局来解决此问题。

我无法修改[栏]

然后将其设为非平凡可复制标准布局类型将是不可能的,因此某些语言实现不会重用填充。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-11-23
  • 1970-01-01
  • 2014-02-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多