public struct Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
public class Program
{
public static void Main()
{
Point point1 = new Point(10, 20);
Point point2 = point1;
point2.X = 30;
Console.WriteLine("Point 1 X: " + point1.X);
Console.WriteLine("Point 2 X: " + point2.X);
}
}
public class Point
{
public int X;
public int Y;
public Point(int x, int y)
{
X = x;
Y = y;
}
}
public class Program
{
public static void Main()
{
Point point1 = new Point(10, 20);
Point point2 = point1;
point2.X = 30;
Console.WriteLine("Point 1 X: " + point1.X);
Console.WriteLine("Point 2 X: " + point2.X);
}
}
내 답:
struct
Point 1 X: 10
point 2 X: 30
class
Point 1 X: 30
Point 2 X: 30
struct는 값 형식으로, x가 point1과 point2에 각각 저장되고 class는 참조형이기 때문에 point2에 point1을 할당하는 것이 서로 같은 참조값을 가진다는 뜻으로 그들이 가르키는 객체가 동일하니 point2를 지정해서 값을 바꾼 것이 point1으로 호출해도 영향을 끼칩니다.
모범 답:
1 - 10 30
구조체는 값 형식이므로 point2.x 값을 바꾸어도 값이 바뀌지 않는다.
2 - 30 30
클래스는 참조 형식이니까 point2.x 를 참조해서 x 값이 모두 30으로 바뀐다.
내 답:
참조 형식은 데이터를 힙 메모리에 저장하고, 변수에는 데이터가 저장된 힙 메모리의 주소가 저장됩니다. 참조 형식의 변수를 다른 변수에 할당하면, 메모리 주소가 복사되어 두 변수가 같은 객체를 참조하게 됩니다. 따라서, 한 변수를 통해 객체를 변경하면, 같은 객체를 참조하는 다른 변수를 통해서도 변경된 내용을 볼 수 있습니다.
값 형식은 데이터를 스택 메모리에 직접 저장합니다. 값 형식의 변수에는 실제 데이터 값이 저장되며, 변수를 다른 변수에 할당할 때는 해당 값의 복사본이 생성되어 할당됩니다. 따라서, 원본 변수와 복사된 변수는 서로 독립적이며, 하나를 변경해도 다른 하나에는 영향을 주지 않습니다.
모범 답:
참조 형식은 힙에 할당되며, 객체의 참조를 저장하고 값 형식은 스택에 할당되며, 실제 데이터를 저장한다 메모리 할당 차이를 언급해주시면 좋습니다.
값 형식은 변수가 실제 데이터를 저장하는 데이터 유형이다. 값을 직접 메모리에 저장한다. >> 스택 메모리에 할당 , 빠르게 접근 가능 , 기본 데이터 타입들 , 구조체가 있다.
참조 형식은 실제 데이터가 저장된 메모리 위치(참조)를 저장하는 데이터 유형이다. >> 힙 메모리에 할당, 더 큰 메모리 공간을 사용하며 동적 메모리 할당에 적합 , 실제 데이터의 참조(메모리 주소)가 복사된다.
내 답:
메모리 관리:
스택은 자동으로 메모리가 관리되며, 힙은 수동(또는 가비지 컬렉터에 의한) 메모리 관리가 필요합니다.
스택 메모리는 프로그램이 시작할 때 크기가 결정되며, 이 크기는 고정입니다. 힙 메모리는 동적으로 메모리가 할당됩니다.
속도:
스택은 힙에 비해 메모리 할당과 해제가 빠릅니다.
크기와 유연성:
스택은 크기가 고정되어 있으며, 힙은 더 유연하게 메모리를 할당하고 확장할 수 있습니다.
사용 목적:
스택은 주로 지역 변수와 메서드 호출을 위해 사용되며, 힙은 동적 메모리 할당과 대규모 데이터 구조를 위해 사용됩니다.
모범 답:
- 스택은 작은 크기의 변수나 지역변수 등을 저장하고 힙은 동적 할당을 통해 큰 크기의 변수 할당이 가능하다고 설명해야 합니다.
- 필요한 메모리의 크기가 언제 결정되는지 같이 언급해주면 좋습니다. (스택 - 컴파일 타임, 힙 - 런타임)
- 메모리 해제 역시 언제 이루어지는지 같이 언급해주면 좋습니다. (스택 - 현재 호출된 함수가 종료; 호출 스택과 같이 설명, 힙 - 가비지 컬렉션)
스택은 컴파일 시간에 크기가 결정되는 변수들을 저장하는데 사용되며, 힙은 런타임에 크기가 결정되거나 변경될 수 있는 데이터를 저장하는 데 사용된다.
내 답:
struct는 스택 메모리에 데이터를 저장하고, class는 힙 메모리에 데이터를 저장합니다. struct는 값 형식이고, class는 참조 형식입니다.
struct는 복사할 때 데이터의 복사본이 생성되고, class는 복사할 때 메모리 주소(참조)가 복사됩니다.
모범 답:
struct는 값 형식으로 스택에 할당되고, 매개변수 전달 시 값이 복사됩니다.
class는 참조 형식으로 힙에 할당되며, 매개변수 전달 시 참조가 전달됩니다.
값 형식 vs. 참조 형식
struct:
값 형식(Value Type)이다.
스택(Stack)에 할당된다.
변수에 struct를 할당하면 실제 데이터의 복사본이 생성됩니다. 즉, struct를 다른 변수에 할당하거나 함수에 전달할 때 데이터가 복사된다.
구조체의 복사본을 수정해도 원래 구조체에는 영향을 미치지 않는다.
class:
참조 형식(Reference Type)이다.
힙(Heap)에 할당된다.
변수에 class 객체를 할당하면 객체의 참조(메모리 주소)가 저장된다. 즉, 객체를 다른 변수에 할당하거나 함수에 전달할 때 데이터의 참조가 전달된다.
객체의 참조를 수정하면 해당 객체의 모든 참조가 영향을 받는다.
메모리 할당
struct:
주로 스택에 할당되지만, struct가 클래스의 필드로 사용되면 힙에 할당될 수 있다.
스택에 할당되므로 할당과 해제가 빠르다.
class:
항상 힙에 할당된다.
힙에 할당되므로 할당과 해제가 상대적으로 느리다.
가비지 컬렉터에 의해 관리되므로 메모리 해제 시점이 불확실하다.
상속
struct:
상속을 지원하지 않는다. 다른 struct나 class로부터 상속받을 수 없으며, 상속할 수도 없다.
인터페이스는 구현할 수 있다.
class:
상속을 지원한다. 다른 클래스에서 상속받을 수 있으며, 상속할 수도 있다.
인터페이스도 구현할 수 있다.
기본 생성자
struct:
기본 생성자가 자동으로 제공된다. 매개변수가 없는 생성자를 정의할 수 없다.
필드를 초기화하지 않아도 된다.
class
기본 생성자를 정의할 수 있다. 매개변수가 없는 생성자를 포함하여 여러 생성자를 정의할 수 있다.
필드는 명시적으로 초기화하거나, 생성자에서 초기화해야 한다.
내 답:
얕은 복사는 참조 타입 필드의 메모리 주소를 공유하지만, 깊은 복사는 참조 타입 필드의 실제 데이터까지 복사하여 주소를 공유하지 않습니다.
얇은 복사로 만들어진 객체는 원본 객체와 참조 타입 필드가 공유되기 때문에 서로 영향을 주지만, 깊은 복사로 만들어진 객체는 원본 객체와 완전히 독립적입니다.
얇은 복사에 비해 깊은 복사는 객체 내부의 모든 참조 타입 필드를 재귀적으로 복사해야하 하므로 구현이 더 복잡합니다.
모범 답:
얕은 복사는 객체의 참조만 복사하여 동일한 객체를 가리키게 합니다. 깊은 복사는 개별 객체를 생성하여 독립적인 데이터를 가지게 합니다.
얕은 복사(Shallow Copy) : 얕은 복사는 객체의 최상위 수준만 복사하며, 객체가 참조하는 하위들(즉, 중첩된 객체들)은 원본 객체와 동일한 참조를 갖게 된다. 이는 객체의 복사본이 원본 객체와 동일한 하위 객체들을 참조하게 됨을 의미된다.
깊은 복사 (Deep Copy) :
깊은 복사는 객체와 그 객체가 참조하는 모든 하위 객체들을 재귀적으로 복사한다. 이는 원본 객체와 복사본 객체가 서로 독립적인 구조를 가지게 됨을 의미한다.
내 답:
박싱과 언박싱은 값 형식과 참조 형식 사이의 변환을 다룹니다.
박싱이 일어날 때, 힙 메모리에 새로운 객체를 위한 공간이 할당됩니다.
값 형식의 인스턴스가 스택에 있을 때, 이 인스턴스의 값이 새로 할당된 힙 메모리 영역으로 복사됩니다.
박싱된 객체의 메모리 주소가 반환됩니다. 이 주소를 통해 힙에 저장된 값에 접근할 수 있습니다.
언박싱이 일어날 때, 객체가 변환하는 값 형식과 호환되는지 확인합니다.
타입 검사를 통과하면, 힙에 저장된 객체의 값이 스택에 할당된 값 형식 변수로 복사됩니다.
모범 답:
박싱은 값 형식을 참조 형식으로 변환하여 힙에 할당하는 과정입니다. 언박싱은 참조 형식을 값 형식으로 변환하여 스택에 복사하는 과정입니다.
박싱(Boxing) : 박싱은 값 형식을 참조 형식으로 변환하는 과정이다. 값 형식을 객체(Object)로 감싸서 힙(Heap) 메모리에 저장하고, 이 객체의 참조를 반환한다.
언박싱(Unboxing) : 언박싱은 참조 형식을 값 형식으로 변환하는 과정이다. 힙에 저장된 객체의 값을 스택에 있는 값 형식 변수로 복사한다.
메모리 관리 : 힙에 할당된 객체는 가비지 컬렉터에 의해 관리된다. 따라서 많은 박싱 작업은 가비지 컬렉션 부담을 증가시킬 수 있다.
[깊은 복사 구현]
여러 종류의 깊은 복사를 구현해봅시다.
새로운 인스턴스를 생성하여 모든 필드들을 복사한 뒤 반환해주는 Clone() 메서드
복사 생성자를 이용한 깊은 복사
public class Character
{
public string name;
public int hp;
public int attack;
public Character()
{
name = "";
hp = 10;
attack = 5;
}
public Character Clone()
{
// ****** CODE HERE ******
//Character newCharacter = new Character();
//newCharacter.name = this.name;
//newCharacter.hp = this.hp;
//newCharacter.attack = this.attack;
//return newCharacter;
return new Character
{
name = this.name,
hp = this.hp,
attack = this.attack
};
// ***********************
}
public Character(Character original)
{
// ****** CODE HERE ******
this.name = original.name;
this.hp = original.hp;
this.attack = original.attack;
// ***********************
}
}