2009-03-20 7 views
7

MSDN은 16 바이트 이하의 클래스는 구조체 [citation]으로 처리하는 것이 더 효율적이라고 말합니다.
왜 그런가요?
구조체가 16 바이트를 넘으면 클래스보다 효율적이지 않거나 동일한 구조체일까요?
클래스가 16 바이트 미만인지 어떻게 결정합니까?
구조체가 클래스처럼 작동하지 못하도록 제한하는 것은 무엇입니까? (매개 변수없는 생성자를 허용하지 않음)구조체에 대한 질문입니다.

+0

여기에서 C# 구조체에 대한 많은 정보를 찾을 수 있습니다. http://stackoverflow.com/questions/85553/when-should-i-use-a-struct-instead-of-a-class –

+0

아마 이미 발견되었지만 MSDN에 더 많은 내용이 있습니다. http://msdn.microsoft.com/en-us/library/ms229017.aspx –

+0

게시하기 전에 _right_을 발견했습니다. 감사! – Malfist

답변

6

는이 질문에 대한 몇 가지 답이있다, 그것은 조금 주관적이다,하지만 내가 생각할 수있는 몇 가지 이유는 다음과 같습니다

  • 구조체는 값 형식이고, 클래스 참조 형이다. 총 저장 용량이 16 바이트 인 경우 각각에 대해 메모리 참조 (4 ~ 8 바이트)를 생성 할 가치가 없을 것입니다.
  • 매우 작은 개체가있을 때 개체에 대한 참조 대신 IL 스택으로 푸시 될 수 있습니다. 이것은 피 호출자 측에서 메모리 비 참조를 제거하기 때문에 일부 코드의 속도를 향상시킬 수 있습니다.
  • 일리노이 강의 수업과 관련된 약간의 "보풀"이 있습니다. 데이터 구조가 매우 작 으면이 보풀이 전혀 사용되지 않으므로 필요없는 여분의 쓰레기가됩니다.

구조체와 클래스 간의 가장 중요한 차이점은 구조체는 값 형식이고 클래스는 참조 형식이라는 점입니다.

+0

오! 죄송합니다 - "CLR", 즉 공용 언어 런타임에 대한 속기 유형의 "Intermediate Language"를 작성해야합니다. .NET 코드를 실행하는 가상 컴퓨터입니다. – Mike

+0

JVM처럼? – Malfist

+0

일리노이 ~ 자바 바이트 코드, CLR ~ JVM – eglasius

0

메모리에서 구조체는 데이터를 직접 보유하지만 클래스는 포인터처럼 작동합니다. 클래스가 값에 대한 참조를 전달하는 동안 구조체를 매개 변수로 전달하여 메서드에 값을 전달 (스택에 복사)하므로 중요한 차이가 있습니다. 구조체가 큰 경우 각 메소드 호출에서 많은 값을 복사하게됩니다. 그것이 정말로 작을 때 값을 복사하고 직접 사용하는 것은 포인터를 복사하고 다른 위치에서 가져 오는 것보다 빠를 것입니다.

제한 사항 : null에 할당 할 수는 있지만 (Nullable <> 사용할 수 있음) 즉시 초기화해야합니다.

+0

MSDN은 구조체가 스택에 저장되는 동안 클래스는 힙에 저장되는 반면 구조체는 스택에 저장됩니다. – Malfist

+1

네, 그렇습니다. 스택 변수는 힙 변수보다 빠르게 탐색 될 수 있습니다.그러나 구조체를 매개 변수로 메서드에 전달하면 메서드가 호출되기 전에 스택에 완전히 복사되지만 클래스의 경우에는 포인터 만 복사됩니다. – Groo

2

이 링크를 확인하면 오늘의 답변 중 하나 인 .NET Type Internals에서 발견되었습니다. 또한 SO와 Googling을 검색하여 구조체와 클래스 간의 차이점에 대한 "참조 유형과 값 유형"을 시도 할 수 있습니다.

구조체가 클래스처럼 작동하지 못하도록 제한하는 것은 무엇입니까?

많은 차이가 있습니다. 예를 들어 struct에서 상속받을 수 없습니다.

가상 메서드를 사용할 수 없으므로 구조체를 사용하여 인터페이스를 구현할 수 없습니다. 구조체의 인스턴스 메소드는 구조체의 private 필드에 액세스 할 수 있지만, 별개의 "helper"함수처럼 작동합니다 (변경 불가능한 구조체의 경우 때때로 개인 데이터에 액세스 할 필요조차 없습니다). 그래서 저는 그것들이 계급 방법처럼 "가치있는"것만 큼 가까이 있지 않다는 것을 알게됩니다.

+0

"구조체에 인스턴스 메소드를 추가하는 데별로 도움이되지 않습니다."-이 부분을 더 확장 할 수 있습니까? mildy usefull, 즉 ToString()을 추가했습니다. –

+0

대부분의 수업은 봉인되어야하지만 귀하의 요점을 보았습니다. – Malfist

+0

@Neil : 조금 어색한 말투로 인해 유감스럽게 생각합니다. – Groo

0

이것은 CLR이 구조체와 클래스를 처리하는 다른 방식 때문입니다. 구조체는 관리되는 힙보다는 스택에 있다는 것을 의미하는 값 유형입니다.구조체를 작게 유지하는 것은 좋은 법칙입니다. 메서드 인수로 전달하기 시작하면 메서드에 전달 될 때 전체 구조체가 복사되므로 오버 헤드가 발생하기 때문입니다.

클래스는 메소드에 대한 참조 사본을 전달하므로 메서드 인수로 사용될 때 오버 헤드가 훨씬 적습니다.

클래스의 크기를 확인하는 가장 좋은 방법은 클래스의 모든 구성원이 필요로하는 바이트 수와 CLR 오버 헤드 항목에 대한 추가 8 바이트를 합하는 것입니다 (동기 블록 인덱스 및 그 물체).

0

구조체는 힙이 아닌 스택에 저장되므로 클래스와 다릅니다. 즉, struct를 매개 변수로 사용하여 메서드를 호출 할 때마다 복사본이 만들어져 메서드에 전달됩니다. 이것이 큰 구조체가 매우 비효율적 인 이유입니다.

그럼에도 불구하고 일부 미묘한 버그가 발생할 수 있기 때문에 구조체 사용을 적극적으로 권장하지 않습니다. 구조체의 필드를 변경할 때 호출자에 대해 반영되지 않을 것입니다 (복사본 만 변경했기 때문에). 이는 클래스와 완전히 다른 동작입니다.

그래서 16 바이트 구조체는 합리적인 최대 크기라고 생각하지만 대부분의 경우 여전히 클래스를 갖는 것이 좋습니다. 여전히 구조체를 만들고 싶다면 적어도 변경 불가능한 구조로 만드십시오.

3

"효율적"이라고 말하면 클래스 또는 구조체를 나타내는 데 필요한 메모리 양을 말합니다.

32 비트 플랫폼에서 개체를 할당하려면 최소 16 바이트가 필요합니다. 64 비트 플랫폼에서 최소 객체 크기는 24 바이트입니다. 따라서 사용 된 메모리의 양을 기준으로 순수하게 보면 16 바이트 미만의 데이터가 들어있는 구조체는 해당 클래스보다 "더 나은"상태가됩니다.

그러나 사용 된 메모리의 양은 전체 이야기가 아닙니다. 값 유형 (구조체)은 참조 유형 (클래스)과 근본적으로 다릅니다. 구조체는 사용하기가 불편할 수 있으며 조심하지 않으면 성능상의 문제가 발생할 수 있습니다.

실제 답변은 물론 상황에 가장 적합한 방법을 사용하는 것입니다. 대부분의 경우 수업을 사용하는 것이 훨씬 낫습니다.

0

구조체의 인스턴스를 복사하는 것은 클래스의 새 인스턴스를 만들고 이전 인스턴스에서 데이터를 복사하는 것보다 시간이 덜 들지만 클래스 인스턴스는 공유 할 수 있으며 struct 인스턴스는 공유 할 수 없습니다. 따라서 "structvar1 = classvar2"를 사용하면 classvar1과 classvar2가 동일한 struct 인스턴스를 참조 할 수 있습니다 (새 인스턴스를 만들지 않고). "structvar1 = structvar2"는 새로운 struct 인스턴스를 복사해야합니다.

새 struct 인스턴스를 작성하는 코드는 최대 16 바이트 크기에 최적화되어 있습니다. 더 큰 구조체는 덜 효율적으로 처리됩니다. 구조체는 구조체를 보유하는 모든 변수가 독립 인스턴스를 보유하는 경우 (즉, 특정 두 변수가 동일한 인스턴스를 보유 할 것으로 기대할 이유가없는 경우)에 유리합니다. 많은 변수가 동일한 인스턴스를 보유 할 수있는 경우에는 이길 수 없습니다 (이길 경우 모두 승리합니다).

관련 문제