繁体   English   中英

包含1个指针的结构的大小

[英]Size of a struct containing 1 Pointer

假设我有以下类模板:

template<typename T>
struct Wrapper {
  T* t_;
  static void check() {
    static_assert(sizeof(Wrapper<T> == sizeof(T*), "Illegal assumption");
  }
};

我查看了C ++ 03标准中的C99标准,但找不到为我在static_assert表示的假设的保证。 我在Visual C ++ 2008和2010(32位)上进行了尝试,并在Linux(64位)上使用了几个编译器选项对gcc进行了测试,发现我的假设得到了证实。

我的问题是:

  • 我的假设对Visual C ++ 2008/2010/11(Windows)是否合理?
  • 对于gcc 4. *(Linux)?
  • 对于编译器标志的任何组合?
  • 您是否知道任何不符合该假设的编译器/平台?

我猜编译器可能会在结构中添加一些填充,例如出于调试目的。 但是,有没有一个编译器实际上可以做到这一点?

编辑:因此,正如您在这里问的是我要实现的目标:
我具有以下签名的成员函数:

Someclass* OtherClass::fn();

我想这样更改签名:

Wrapper<Someclass> OtherClass::fn();

该包装器的作用类似于某些智能指针,即,它关心指针的生命周期,因此在超出范围时将其释放。 由于该函数是跨dll边界调用的,因此我想确保在所有情况下(例如,编译器设置等),返回值(现在是一种具体类型,而不仅仅是一个哑指针)的大小都与指针相同将会。 计划/希望将支持调试/发布应用程序/ dll构建的所有组合。
您可能会问:不,我不能使用boost :: shared_ptr <>,std :: shared_ptr <>,std :: unique_ptr <>等,因为我们不想将Boost公开给dll用户,我们尚不支持C ++ 11。

如果您要假设它并且进行了编译时检查,请继续。 大概可以从中受益。

您不能保证有关填充的任何信息,但是通常使用填充来进行对齐,以使该类型的数组将数组的每个成员(以及结构的每个成员)正确对齐。 通常,本机指针已经是要对齐的正确大小,因此不需要填充,但是您不能保证做到这一点。

您不能使用gcc来检查这件事-它取决于目标体系结构,而不仅取决于编译器。

查看标准,我在§9.2 [class.mem]中发现了两个有趣的地方

17 /如果两个标准布局结构(条款9)类型具有相同数量的非静态数据成员,并且对应的非静态数据成员(按声明顺序)具有布局兼容类型(3.9),则它们是布局兼容的。

因此,其中只有一个指针的两个struct是布局兼容的(因此,如果您的断言适用于此类型,则它适用于所有类型)。

20 /指向标准布局结构对象的指针(使用reinterpret_cast进行了适当转换)指向其初始成员(或者,如果该成员是位字段,则指向它所在的单元),反之亦然。 [注意:因此,在标准布局结构对象中可能会存在未命名的填充,但在其开始时可能没有,这是实现适当对齐所必需的。 —尾注]

在注释中,我们了解到结构的开头不能有填充。


根据您的目标, 20 /可能就足够了。 这意味着这有效:

void check(T* t) {
    Wrapper<T>* w = reinterpret_cast<Wrapper<T>*>(t);
    assert(w->t_ == t);
}

我想说您的假设对于大多数编译器和标志都是合理的。

对于任何T,编译器都能够创建T的数组,这些数组必须是连续的,因此它必须能够创建它而无需填充。 这样,将其放入您的结构中的任何填充将完全是可选的,而不是必需的。

另一方面,我可以肯定地说,没有C或C ++标准可以保证您的要求。 关于它的最接近的保证来自于以下事实:在C ++中,它是一个标准布局结构,它限制了C ++编译器像C编译器那样对字段进行布局,因此成员必须以升序排列,开头没有填充-但成员之间和/或最后一个成员之后仍允许填充。

底线:如果您有指向第一个成员的指针,则可以安全地转换为指向struct的指针(反之亦然)。 如果您要自己做一些事情,例如创建一个数组并像其他数组一样对其进行索引,那么您就自己一个人了–它起作用的机会非常好,但是我敢肯定,该标准不会保证。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM