string vs StringBuilder
예를 들어, int의 경우를 살펴보자. int는 값 타입(value type)이면서 가변(mutable)이다.
값 타입은 데이터 변경 시에 새로운 메모리 할당이 일어나지 않는다. 이미 생성된 메모리의 데이터가 변경된다.
static void Main(string[] args)
{
int a = 100;
int b = a;
a = 300;
Console.WriteLine($"a : {a}"); // 300
Console.WriteLine($"b : {b}"); // 100
}
string의 경우를 살펴보자. string은 참조 타입(reference type)이면서 불변(immutable)이다.
static void Main(string[] args)
{
string s = "Hello World";
string s1 = s;
a = "World Hello"; // 메모리 재할당이 일어난다.
Console.WriteLine($"a : {a}"); // "World Hello"
Console.WriteLine($"b : {b}"); // "Hello World"
}
참조 타입은 Heap memory에 할당된 주소를 가진다. 그렇다면 데이터 변경 시에 어떤 일이 일어나는 것일까?
string의 경우 가변처럼 작동하는 거 같지만 사실 내부적으로는 매번 메모리 할당이 일어나고 있다. 그래서 string을 매우 많이 변경하면 메모리에 오버헤드가 발생하게 된다.
(주로 string과 StringBuilder를 비교하면서 자주 언급되는 내용)
static void Main(string[] args)
{
string s = "world";
string s1 = s;
s += "hello"; // 메모리 할당
s += "1"; // 메모리 할당
s += "2"; // 메모리 할당
Console.WriteLine(s); // "worldhello12"
Console.WriteLine(s1); // "world"
}
string이 불변이라는 것에 의문을 제기하는 많은 질문 글들이 존재한다.
(불변이 맞다. 매번 새로 힙 영역에 할당되는 것이다.)
그렇다면 StringBuilder의 경우는 어떻게 다른가? StringBuilder는 참조 타입(reference type)이면서 가변(mutable)이다.
static void Main(string[] args)
{
StringBuilder a = new StringBuilder();
StringBuilder b = new StringBuilder();
a.Append("1");
b = a;
a.Append("3");
Console.WriteLine($"a : {a}"); // 13
Console.WriteLine($"b : {b}"); // 13
}
값 타입(Value Type)과 참조 타입(Reference Type) 분류
- 하늘색으로 표현한 부분이 값 타입(Value Type)
- 파란색으로 표현한 부분이 참조 타입(Reference Type)
System.ValueType, bool, byte, int, float, char, enum, struct로 정의하는 타입들이 값 타입(value Type)이다.
object, string, System.Array, class로 정의하는 타입들이 참조 타입(Reference Type)이다.
값 타입(Value Type)과 참조 타입(Reference Type) 동작 차이
C#에서는 왜 값 타입과 참조 타입을 구분하였을까?
- 메모리가 작은 변수는 값을 복사하는게 빠르다.
- 메모리가 큰 변수는 값이 아니라 주소를 복사하는 게 빠르고 효율적이다.
상대적으로 메모리가 클 가능성이 높은 참조 타입 변수의 복사는 값 복사가 아닌 주소값(4바이트, 8바이트)을 복사함으로써 메모리 주소를 복사한 것이지만 프로그래머는 이를 마치 전체 값이 복사된 것처럼 사용할 수 있다.
C++ 프로그래머의 경우 일반 객체와 포인터 객체를 구분해서 작성하지만 C#의 경우에는 프로그래머가 이에 대해 몰라도 코드를 작성하는데 아무 지장이 없다. (편의성 제공) 하지만 C# 내부 작동 개념을 알아야지 효율적인 프로그래밍이 가능할 것이다.
함께 읽으면 좋은 글
참고 사이트
'프로그래밍 > C#' 카테고리의 다른 글
C# 문자열 정렬하기 (0) | 2024.01.15 |
---|---|
C# Call by value와 Call by reference에 대해서 (0) | 2024.01.12 |
BitConverter.ToInt16 메서드에 대해서 (1) | 2024.01.08 |
C# List Sort()를 사용해서 정렬하기 (1) | 2023.11.23 |
C# 8 : using 선언 (0) | 2023.11.10 |
댓글