다음을 통해 공유


STL/CLR 컨테이너

STL/CLR 라이브러리는 C++ 표준 라이브러리에 있는 컨테이너와 비슷하지만 .NET Framework의 관리되는 환경 내에서 실행됩니다. 실제 C++ 표준 라이브러리를 최신 상태로 유지하지 않으며 레거시 지원을 위해 기본.

이 문서에서는 컨테이너 요소에 대한 요구 사항, 컨테이너에 삽입할 수 있는 요소 유형 및 컨테이너의 요소에 대한 소유권 문제와 같은 STL/CLR의 컨테이너에 대한 개요를 제공합니다. 적절한 경우 네이티브 C++ 표준 라이브러리와 STL/CLR 간의 차이점이 멘션.

컨테이너 요소에 대한 요구 사항

STL/CLR 컨테이너에 삽입된 모든 요소는 특정 지침을 준수해야 합니다. 자세한 내용은 STL/CLR 컨테이너 요소에 대한 요구 사항을 참조 하세요.

유효한 컨테이너 요소

STL/CLR 컨테이너는 다음 두 가지 요소 유형 중 하나를 보유할 수 있습니다.

  • 참조 형식에 대한 핸들입니다.

  • 참조 형식.

  • Unboxed 값 형식입니다.

STL/CLR 컨테이너에는 boxed 값 형식을 삽입할 수 없습니다.

참조 형식에 대한 핸들

참조 형식에 대한 핸들을 STL/CLR 컨테이너에 삽입할 수 있습니다. CLR을 대상으로 하는 C++의 핸들은 네이티브 C++의 포인터와 유사합니다. 자세한 내용은 개체 연산자 핸들(^)을 참조하세요.

예시

다음 예제에서는 Cliext::set에 Employee 개체에 핸들을 삽입하는 방법을 보여 있습니다.

// cliext_container_valid_reference_handle.cpp
// compile with: /clr

#include <cliext/set>

using namespace cliext;
using namespace System;

ref class Employee
{
public:
    // STL/CLR containers might require a public constructor, so it
    // is a good idea to define one.
    Employee() :
        name(nullptr),
        employeeNumber(0) { }

    // All STL/CLR containers require a public copy constructor.
    Employee(const Employee% orig) :
        name(orig.name),
        employeeNumber(orig.employeeNumber) { }

    // All STL/CLR containers require a public assignment operator.
    Employee% operator=(const Employee% orig)
    {
        if (this != %orig)
        {
            name = orig.name;
            employeeNumber = orig.employeeNumber;
        }

        return *this;
    }

    // All STL/CLR containers require a public destructor.
    ~Employee() { }

    // Associative containers such as maps and sets
    // require a comparison operator to be defined
    // to determine proper ordering.
    bool operator<(const Employee^ rhs)
    {
        return (employeeNumber < rhs->employeeNumber);
    }

    // The employee's name.
    property String^ Name
    {
        String^ get() { return name; }
        void set(String^ value) { name = value; }
    }

    // The employee's employee number.
    property int EmployeeNumber
    {
        int get() { return employeeNumber; }
        void set(int value) { employeeNumber = value; }
    }

private:
    String^ name;
    int employeeNumber;
};

int main()
{
    // Create a new employee object.
    Employee^ empl1419 = gcnew Employee();
    empl1419->Name = L"Darin Lockert";
    empl1419->EmployeeNumber = 1419;

    // Add the employee to the set of all employees.
    set<Employee^>^ emplSet = gcnew set<Employee^>();
    emplSet->insert(empl1419);

    // List all employees of the company.
    for each (Employee^ empl in emplSet)
    {
        Console::WriteLine("Employee Number {0}: {1}",
            empl->EmployeeNumber, empl->Name);
    }

    return 0;
}

참조 형식

참조 형식에 대한 핸들이 아닌 참조 형식을 STL/CLR 컨테이너에 삽입할 수도 있습니다. 여기서 기본 차이점은 참조 형식의 컨테이너가 삭제되면 해당 컨테이너 내의 모든 요소에 대해 소멸자가 호출된다는 것입니다. 참조 형식에 대한 핸들 컨테이너에서는 이러한 요소에 대한 소멸자가 호출되지 않습니다.

예시

다음 예제에서는 Employee 개체 cliext::set를 삽입하는 방법을 보여줍니다.

// cliext_container_valid_reference.cpp
// compile with: /clr

#include <cliext/set>

using namespace cliext;
using namespace System;

ref class Employee
{
public:
    // STL/CLR containers might require a public constructor, so it
    // is a good idea to define one.
    Employee() :
        name(nullptr),
        employeeNumber(0) { }

    // All STL/CLR containers require a public copy constructor.
    Employee(const Employee% orig) :
        name(orig.name),
        employeeNumber(orig.employeeNumber) { }

    // All STL/CLR containers require a public assignment operator.
    Employee% operator=(const Employee% orig)
    {
        if (this != %orig)
        {
            name = orig.name;
            employeeNumber = orig.employeeNumber;
        }

        return *this;
    }

    // All STL/CLR containers require a public destructor.
    ~Employee() { }

    // Associative containers such as maps and sets
    // require a comparison operator to be defined
    // to determine proper ordering.
    bool operator<(const Employee^ rhs)
    {
        return (employeeNumber < rhs->employeeNumber);
    }

    // The employee's name.
    property String^ Name
    {
        String^ get() { return name; }
        void set(String^ value) { name = value; }
    }

    // The employee's employee number.
    property int EmployeeNumber
    {
        int get() { return employeeNumber; }
        void set(int value) { employeeNumber = value; }
    }

private:
    String^ name;
    int employeeNumber;
};

int main()
{
    // Create a new employee object.
    Employee empl1419;
    empl1419.Name = L"Darin Lockert";
    empl1419.EmployeeNumber = 1419;

    // Add the employee to the set of all employees.
    set<Employee>^ emplSet = gcnew set<Employee>();
    emplSet->insert(empl1419);

    // List all employees of the company.
    for each (Employee^ empl in emplSet)
    {
        Console::WriteLine("Employee Number {0}: {1}",
            empl->EmployeeNumber, empl->Name);
    }

    return 0;
}

Unboxed 값 형식

STL/CLR 컨테이너에 unboxed 값 형식을 삽입할 수도 있습니다. unboxed 값 형식은 참조 형식으로 boxed되지 않은 값 형식입니다.

값 형식 요소는 표준 값 형식(예: 표준 int값 형식) 중 하나이거나 사용자 정의 값 형식(예: value class)일 수 있습니다. 자세한 내용은 클래스 및 구조체를 참조 하세요.

예시

다음 예제에서는 Employee 클래스를 값 형식으로 만들어 첫 번째 예제를 수정합니다. 이 값 형식은 첫 번째 예제와 cliext::set 마찬가지로 삽입됩니다.

// cliext_container_valid_valuetype.cpp
// compile with: /clr

#include <cliext/set>

using namespace cliext;
using namespace System;

value class Employee
{
public:
    // Associative containers such as maps and sets
    // require a comparison operator to be defined
    // to determine proper ordering.
    bool operator<(const Employee^ rhs)
    {
        return (employeeNumber < rhs->employeeNumber);
    }

    // The employee's name.
    property String^ Name
    {
        String^ get() { return name; }
        void set(String^ value) { name = value; }
    }

    // The employee's employee number.
    property int EmployeeNumber
    {
        int get() { return employeeNumber; }
        void set(int value) { employeeNumber = value; }
    }

private:
    String^ name;
    int employeeNumber;
};

int main()
{
    // Create a new employee object.
    Employee empl1419;
    empl1419.Name = L"Darin Lockert";
    empl1419.EmployeeNumber = 1419;

    // Add the employee to the set of all employees.
    set<Employee>^ emplSet = gcnew set<Employee>();
    emplSet->insert(empl1419);

    // List all employees of the company.
    for each (Employee empl in emplSet)
    {
        Console::WriteLine("Employee Number {0}: {1}",
            empl.EmployeeNumber, empl.Name);
    }

    return 0;
}

컨테이너 에 값 형식에 대한 핸들을 삽입하려고 하면 컴파일러 오류 C3225 가 생성됩니다.

성능 및 메모리 영향

핸들을 사용하여 형식을 참조할지 아니면 값 형식을 컨테이너 요소로 사용할지 결정할 때 몇 가지 요소를 고려해야 합니다. 값 형식을 사용하기로 결정한 경우 요소가 컨테이너에 삽입될 때마다 요소의 복사본이 만들어집니다. 작은 개체의 경우 문제가 되지 않지만 삽입되는 개체가 크면 성능이 저하될 수 있습니다. 또한 값 형식을 사용하는 경우 각 컨테이너에 요소의 자체 복사본이 있기 때문에 한 요소를 동시에 여러 컨테이너에 저장할 수 없습니다.

대신 핸들을 사용하여 형식을 참조하려는 경우 컨테이너에 삽입할 때 요소의 복사본을 만들 필요가 없으므로 성능이 향상될 수 있습니다. 또한 값 형식과 달리 동일한 요소가 여러 컨테이너에 있을 수 있습니다. 그러나 핸들을 사용하기로 결정한 경우 핸들이 유효하고 참조하는 개체가 프로그램의 다른 곳에서 삭제되지 않았는지 확인해야 합니다.

컨테이너의 소유권 문제

STL/CLR의 컨테이너는 값 의미 체계에서 작동합니다. 컨테이너에 요소를 삽입할 때마다 해당 요소의 복사본이 삽입됩니다. 참조와 유사한 의미 체계를 가져오려면 개체 자체가 아닌 개체에 핸들을 삽입할 수 있습니다.

핸들 개체 컨테이너의 clear 또는 erase 메서드를 호출할 때 핸들이 참조하는 개체는 메모리에서 해제되지 않습니다. 개체를 명시적으로 삭제하거나 이러한 개체가 관리되는 힙에 있으므로 개체가 더 이상 사용되지 않는다고 판단되면 가비지 수집기가 메모리를 해제하도록 허용해야 합니다.

참고 항목

C++ 표준 라이브러리 참조