对齐非POD结构的缓存

时间:2012-11-27 09:57:57

标签: c++

假设下面有非POD结构,对齐是否生效?如果没有,会有什么期待?

struct S1
{
    string s;
    int32_t i;
    double d;
} __attribute__ ((aligned (64)));

编辑:下面的示例代码的输出是64甚至s被设置为长字符串。

int main(int argc,char *argv[])
{

        S1 s1;

        s1.s = "123451111111111111111111111111111111111111111111111111111111111111111111111111";
        s1.i = 100;
        s1.d = 20.123;
        printf("%ld\n", sizeof(s1));
        return 1;
}

2 个答案:

答案 0 :(得分:1)

C ++中对象的大小永远不会改变。它是编译时间常量。它必须是,因为编译器需要知道为对象分配多少空间。事实上,sizeof(s1)只是sizeof(S1)的别名,后者不涉及任何实例。

std::string是一个小对象,它将指针包装到字符数组并重新分配该数组以适应您设置的值。所以字符串本身存储在S1对象之外。

__attribute__ ((aligned (64)))不是标准C ++,而是GCC扩展。即使对于非POD对象,它也很荣幸。它只是告诉编译器将结构的大小四舍五入到下一个64字节的倍数。

虽然非POD对象很受尊重,但我无法想到将它用于一个POD对象的理由,并且只能想到将它用于POD对象的原因很少。默认对齐是合理的。你不需要调整它。

答案 1 :(得分:0)

是的,对齐在GCC中生效。

示例代码:

#include <string>
#include <iostream>
#include <cstddef>
using namespace std;


struct S1
{
    string s;
    int i;
    double d;
} __attribute__ ((aligned (64)));

struct S2
{
    string s;
    int i;
    double d;
} __attribute__ ((aligned)); // let the compiler decide

struct S3
{
    string s;
    int i;
    double d;
};

int main() {
    cout << "S1 " << sizeof(S1) << endl;
    cout << "S2 " << sizeof(S2) << endl;
    cout << "S3 " << sizeof(S3) << endl;
}

输出:

S1 64
S2 16
S3 16

另外:您发现S1是非POD。请注意,std::string允许在外部存储其数据(通常这样做是因为数据可以是任意长度,因此必须动态分配内存缓冲区。)

请记住,sizeof仅在编译期间计算,不能依赖于运行时值。具体来说,您不能以这种方式查询动态分配的内存大小。

还要记住数组中的每个元素总是属于同一类型,因此大小也相同。