#include <iostream>
using namespace std;
class Cat {
public:
void speak();
private:
int mAge; //4bytes
}
int main() {
cout << sizeof(Cat) << '\n';
Cat stackCat;
Cat * heapCatPtr = new Cat();
delete heapCatPtr
return 0;
}
class를 가지고 object를 만드는데
main함수의 Cat stackCat;이라 하면 proccess memory에서 stack위에 stackCat이라는 object가 생기고
이 공간은 4bytes를 차지한다.
Cat * heapCatPtr = new Cat();라 하면 heap에 4bytes의 Cat object가 생기고
64bits환경의 경우 stack에 8bytes크기의 heapCatptr가 이 heap을 가리키게 된다.
heap memory를 사용하면 필요없을 때 해제를 해줘야 memory leak이 일어나지 않기 때문에
안전하게 사용하기위해서는 smart pointer를 사용하는 것이 좋다.
#include <iostream>
class alignas(32) Cat
{
public:
void speak();
private:
double d8;//8 bytes
int i4a; //4 bytes
int i4b; //4 bytes
};
int main()
{
Cat stackCat;
Cat cats[100];
//prefer std::array
std::cout << sizeof(stackCat) << std::endl;
//16bytes
return 0;
}
라고 했을 때
sizeof(stackCat)을 실행해보면 16bytes가 나오지만
int i4a; //4 bytes
double d8;//8 bytes
int i4b; //4 bytes
순서로 실행해보면 24bytes가 나온다.
이유는 멤버 변수는 그 크기의 배수의 위치에서 시작되어야한다.
예를 들어 int의 경우 4, 8, 16... 4의 배수에서 시작되어야 한다.
두번째 법칙은 object의 전체 크기는 가장 큰 멤버 변수의 크기의 배수가 되어야한다는 것이다.

객체는 또한 배열로 가질 수 있는데,
Cat cats[100];처럼 선언하면 된다.
일반적으로 이런 배열은 문제가 없지만 가속화된 병렬 프로그래밍을 하게된다면 이런 배열은 문제가 될 수 있다.
대부분의 cpu는 여러개의 코어가 들어있는 멀티코어 시스템을 가지고 있는데
cpu는 데이터 접근시간을 최소화 하기위해 cache를 가지고 있고
cache의 가장 작은 단위인 cache line은 일반적으로 64bytes를 가진다.
이 때 문제는 L1 cache는 코어마다 각각 가지고 있기 때문에 각각의 코어가 같은 공간에 접근하게되면
false sharing이라는 문제가 일어난다.
즉 하드웨어적 구조 때문에 데이터를 64bytes로 자르게되고 잘라진 블록이 다른 core에 들어갈 수 있기 때문이다.

alignas specifier을 이용하면 이를 방지할 수 있는데,
class alignas(32) Cat {...}로 선언하게되면
class 뒷 부분에 padding을 넣어주어 32bytes로 만들어준다.
이러면 64bytes에서 잘리더라도 32bytes단위이므로 중간에 잘리지 않아 false sharing문제가 일어나지 않는다.