【发布时间】:2021-12-18 11:41:16
【问题描述】:
我有以下类,它的对齐方式是 8,大小是 40 字节(使用 gcc v11.2 64 位编译)。
class Foo
{
public:
inline Foo( ) = default;
/*
other member functions such as
move ctor and move assignment operator etc.
*/
private:
mutable std::vector< std::vector<char> > _characterMatrix; // occupies 24 bytes on the stack
int _Y_AxisLen; // 4 bytes
int _X_AxisLen; // 4 bytes
char _fillCharacter; // 1 byte
inline static const std::unordered_set<char> CHAR_SET { '/', '\\', '|', '-' }; // static member so nothing
};
还有这句话:
std::cout << "Size: " << sizeof( Foo) << " --- alignment: " << alignof( Foo) << '\n';
生成:
Size: 40 --- alignment: 8
类的大小实际上是8(向量obj的大小成员)+ 8(向量obj的容量成员)+ 8(指向向量obj堆上内存块的qword指针)+ 4(int)+ 4 (int) + 1(char)。所以 8+8+8+4+4+1 == 33 字节。每次初始化 Foo 的实例时都会浪费 7 个字节。
所以我的问题是,有没有办法将尺寸减小到 36?
我也试过这个:
class alignas( 4 ) Foo
{
public:
inline Foo( ) = default;
/*
other member functions such as
move ctor and move assignment operator etc.
*/
private:
mutable std::vector< std::vector<char> > _characterMatrix;
int _Y_AxisLen;
int _X_AxisLen;
char _fillCharacter;
inline static const std::unordered_set<char> CHAR_SET { '/', '\\', '|', '-' };
};
但是编译器忽略了 alignas(4)。大小还是 40。
编辑:在阅读了一些 cmets 之后,我注意到在许多 STL 实现中,std::vector 对象没有指针、大小和容量成员,而是有 3 个指针(每个指针大小为 8 个字节所以总共有 24 个)。
【问题讨论】:
-
在一个完全不相关的注释上:另见What are the rules about using an underscore in a C++ identifier? 以下划线开头的符号后跟一个大写字母(例如
_Y_AxisLen)在所有范围和情况下都是保留的。 -
AFAIK - 向量是 3 个指针(begin、end、end_of_capacity) - 但仍然 - 它的大小与您编写的相同 (3*p == p + s + c)
-
@PiotrNycz 标准库可以将其实现为 3 个指针或 1 个指针和 2 个大小(或完全其他的东西),标准并未仅规定实现所需的行为
-
您担心节省 4 个字节并且您表示一个带有向量向量的矩阵。这两个不属于同一个房间。
标签: c++ class gcc compiler-optimization memory-alignment