참조 형식에 대한 C++ 스택 의미 체계
Visual Studio 2005 이전에는 가비지 수집 힙에서 개체를 만든 연산자를 사용하여 new
참조 형식의 인스턴스만 만들 수 있습니다. 그러나 이제 스택에 네이티브 형식의 인스턴스를 만드는 데 사용하는 것과 동일한 구문을 사용하여 참조 형식의 인스턴스를 만들 수 있습니다. 따라서 참조 형식의 개체를 만들기 위해 ref new, gcnew를 사용할 필요가 없습니다. 또한 개체가 범위를 벗어나면 컴파일러가 개체의 소멸자를 호출합니다.
설명
스택 의미 체계를 사용하여 참조 형식의 인스턴스를 만들 때 컴파일러는 내부적으로 가비지 수집된 힙(사용)에 인스턴스를 gcnew
만듭니다.
함수의 시그니처 또는 반환 형식에 값별 참조 형식의 인스턴스가 포함된 경우 함수는 메타데이터에 특수 처리(modreq 포함)가 필요한 것으로 표시됩니다. 이 특수 처리는 현재 Visual C++ 클라이언트에서만 제공됩니다. 다른 언어는 현재 스택 의미 체계로 만든 참조 형식을 사용하는 함수 또는 데이터 사용을 지원하지 않습니다.
스택 의미 체계 대신 (동적 할당)을 사용하는 gcnew
한 가지 이유는 형식에 소멸자가 없는 경우입니다. 또한 Visual C++가 아닌 다른 언어에서 함수를 사용하려는 경우 함수 서명에 스택 의미 체계를 사용하여 만든 참조 형식을 사용할 수 없습니다.
컴파일러는 참조 형식에 대한 복사 생성자를 생성하지 않습니다. 따라서 서명에서 값별 참조 형식을 사용하는 함수를 정의하는 경우 참조 형식에 대한 복사 생성자를 정의해야 합니다. 참조 형식의 복사 생성자에는 다음과 같은 형식 R(R%){}
의 서명이 있습니다.
컴파일러는 참조 형식에 대한 기본 할당 연산자를 생성하지 않습니다. 할당 연산자를 사용하면 스택 의미 체계를 사용하여 개체를 만들고 스택 의미 체계를 사용하여 만든 기존 개체로 초기화할 수 있습니다. 참조 형식의 대입 연산자에는 다음과 같은 형식 void operator=( R% ){}
의 서명이 있습니다.
형식의 소멸자가 중요한 리소스를 해제하고 참조 형식에 스택 의미 체계를 사용하는 경우 소멸자를 명시적으로 호출하거나 호출 delete
할 필요가 없습니다. 참조 형식 의 소멸자에 대한 자세한 내용은 방법: 클래스 및 구조체 정의 및 사용(C++/CLI)의 소멸자 및 종료자를 참조하세요.
컴파일러에서 생성된 할당 연산자는 다음과 같이 일반적인 표준 C++ 규칙을 따릅니다.
형식이 참조 형식에 대한 핸들인 비정적 데이터 멤버는 단순 복사됩니다(형식이 포인터인 비정적 데이터 멤버처럼 처리됨).
형식이 값 형식인 비정적 데이터 멤버는 단순 복사됩니다.
형식이 참조 형식의 인스턴스인 비정적 데이터 멤버는 참조 형식의 복사 생성자에 대한 호출을 호출합니다.
또한 컴파일러는 스택 의미 체계를 사용하여 만든 참조 형식의 인스턴스를 기본 핸들 형식으로 변환하는 단항 연산자를 제공합니다 %
.
다음 참조 형식은 스택 의미 체계와 함께 사용할 수 없습니다.
예제
설명
다음 코드 샘플에서는 스택 의미 체계를 사용하여 참조 형식의 인스턴스를 선언하는 방법, 할당 연산자 및 복사 생성자의 작동 방식 및 스택 의미 체계를 사용하여 만든 참조 형식으로 추적 참조를 초기화하는 방법을 보여 줍니다.
코드
// stack_semantics_for_reference_types.cpp
// compile with: /clr
ref class R {
public:
int i;
R(){}
// assignment operator
void operator=(R% r) {
i = r.i;
}
// copy constructor
R(R% r) : i(r.i) {}
};
void Test(R r) {} // requires copy constructor
int main() {
R r1;
r1.i = 98;
R r2(r1); // requires copy constructor
System::Console::WriteLine(r1.i);
System::Console::WriteLine(r2.i);
// use % unary operator to convert instance using stack semantics
// to its underlying handle
R ^ r3 = %r1;
System::Console::WriteLine(r3->i);
Test(r1);
R r4;
R r5;
r5.i = 13;
r4 = r5; // requires a user-defined assignment operator
System::Console::WriteLine(r4.i);
// initialize tracking reference
R % r6 = r4;
System::Console::WriteLine(r6.i);
}
출력
98
98
98
13
13