Stroustrup Empty class에 대한 내용 읽어보기

2015. 3. 25. 04:50프로그래밍/C/C++

728x90
728x90

1. 원문

Why is the size of an empty class not zero?

To ensure that the addresses of two different objects will be different. For the same reason, "new" always returns pointers to distinct objects. Consider:

	class Empty { };

	void f()
	{
		Empty a, b;
		if (&a == &b) cout << "impossible: report error to compiler supplier";

		Empty* p1 = new Empty;
		Empty* p2 = new Empty;
		if (p1 == p2) cout << "impossible: report error to compiler supplier";
	}	

There is an interesting rule that says that an empty base class need not be represented by a separate byte:

	struct X : Empty {
		int a;
		// ...
	};

	void f(X* p)
	{
		void* p1 = p;
		void* p2 = &p->a;
		if (p1 == p2) cout << "nice: good optimizer";
	}

This optimization is safe and can be most useful. It allows a programmer to use empty classes to represent very simple concepts without overhead. Some current compilers provide this "empty base class optimization".


2. 해석

* 원문을 직접 해석했으므로 실제 의미와 다를 수 있습니다. 정확한 의미는 원문을 직접 보시길 권장합니다. 번역자 - 조민혁.


 

 

왜 빈 클래스는 사이즈가 0이 아닌가?


이것은 다른 두 객체의 주소가 다름을 보장하기 위해서이다. 같은 이유로,  new는 항상 서로 다른 객체의 주소를 반환한다.

이 것을 한번 생각해보자.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <iostream>
using namespace std;
 
class Empty { };
 
void main()
{
    Empty a, b;
    if (&a == &b) cout << "impossible: report error to compiler supplier";
 
    Empty* p1 = new Empty;
    Empty* p2 = new Empty;
    if (p1 == p2) cout << "impossible: report error to compiler supplier";
}    
cs


 


생성된 빈 클래스들이 서로 다른 주소를 가지고 있는 것을 확인할 수 있다.

여기 재밌는 규칙이 있다. 그것은 빈 기본 클래스는 별도의 분리된 한 바이트로 나타낼 필요는 없다는 것이다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
using namespace std;
 
class Empty { };
 
class X : Empty 
{
        int a;
        // ...
};
 
void main()
{
    X *= new X;
    void* p1 = p;
    void* p2 = &p->a;
    if (p1 == p2) cout << "nice: good optimizer";
}    
cs



 


 

이 최적화는 안전하고 매우 유용하다. 프로그래머는 빈 클래스를 오버헤드 없이 간단한 개념으로 나타내어 이용할 수 있습니다.


최근 몇몇의 컴파일러들은 이 빈 기본 클래스 최적화를 제공하고 있다.


3. 실험


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <iostream>
using namespace std;
 
class Empty { };
 
class Empty2 : Empty { };
 
class ClassA : Empty 
{
    char a;
};
 
class ClassB : Empty
{
    int b;
};
 
class ClassC : ClassB
{
    double c;
};
 
void main()
{
    puts("실험");
}    
cs



우선 빈 클래스의 객체는 1바이트의 크기를 가진다.

결과에서 알 수 있듯이 Empty 클래스의 객체는 1바이트의 크기를 가진다.


왜 1바이트인가?

빈 클래스는 기본적으로 아무것도 없는 클래스이지만 그 객체는 1바이트의 크기를 가진다.

크기가 0일 때의 문제점은 첫 번째는 '포인터 연산'이다.

내부적으로 sizeof(class)만큼 구현된 포인터 연산의 크기가 0이라면 ptr++을 해도 같은 주소에서 머물게 된다.

그리고 두 번째는 메모리에 객체를 할당하는 문제때문이다.

크기가 0이라면 메모리상에서 실체화 할 수 없고 이들을 주소로 구분하는 것이 불가능할 것이다.

그래서 EBCO는 해당 빈 클래스의 객체에 1바이트의 메모리를 할당하여 이런문제를 해결한다.


상속을 받았는데 왜 1바이트가 늘어나지 않는가?

위 예제에서 Empty2 클래스에 Empty 클래스를 상속했다. 빈 클래스에 빈 클래스를.

여기서 컴파일러의 EBCO 옵션이! 빈 클래스가 베이스 클래스가 되었을 때 최적화 옵션이 적용된 것이다.

ClassA, ClassB에도 빈 클래스를 베이스 클래스로 주었지만 객체의 크기는 1바이트가 증가하지 않고

최적화 옵션이 적용된 것을 확인했다.

EBCO는 C++의 구조체도 지원한다.

728x90
반응형

'프로그래밍 > C/C++' 카테고리의 다른 글

가변인자  (0) 2015.03.31
friend  (0) 2015.03.30
__forceinline, __inline, inline 함수 조사  (0) 2015.03.29
[c++] main함수의 인자 argc, argv  (0) 2015.03.07
부동소수점과 예시  (4) 2015.03.06
C와 C++의 차이점  (0) 2015.02.23
기호 이름 읽는 법  (0) 2015.02.18