[]를 사용할 때 C ++ 맵 유형 인수에 빈 생성자가 필요한 이유는 무엇입니까?


99

참조 C ++ 표준 목록과 기본 - 작도 유형

중요한 문제는 아니지만 특정 인수없이 클래스가 인스턴스화되는 것을 원하지 않기 때문에 성가신 일입니다.

#include <map>

struct MyClass
{
    MyClass(int t);
};

int main() {
    std::map<int, MyClass> myMap;
    myMap[14] = MyClass(42);
}

이것은 다음과 같은 g ++ 오류를 제공합니다.

/usr/include/c++/4.3/bits/stl_map.h:419 : 오류 : 'MyClass ()'호출에 일치하는 함수가 없습니다.

기본 생성자를 추가하면 잘 컴파일됩니다. 잘못된 구문으로 인한 것이 아니라고 확신합니다.


위의 코드는 MyType에 대한 typedef가 제공되고 클래스 끝에 세미콜론이 추가 된 경우 MinGW (g ++ 3.4.5) 및 MSVC ++ 2008에서 잘 컴파일됩니다. 다른 작업을 수행해야합니다 (예 : bb에서 언급 한 operator [] 호출) . 전체 코드 를 게시하십시오 .
j_random_hacker

아, 맞아요. 할 것입니다.
Nick Bolton

예, myMap을 사용하지 않으면 map 클래스를 위해 무엇을 컴파일해야하는지 알 수 없습니다. 어떤 stl 라이브러리 공급자와 버전도 도움이 될 수 있습니다.
Greg Domjan

답변:


165

이 문제는 operator []와 함께 발생합니다. SGI 문서에서 인용 :

data_type& operator[](const key_type& k)-특정 키와 관련된 개체에 대한 참조를 반환합니다. 지도에 이러한 객체가 아직 포함되지 않은 경우 operator[] 기본 객체를 삽입합니다 data_type().

기본 생성자가없는 경우 삽입 / 찾기 함수를 사용할 수 있습니다. 다음 예제는 잘 작동합니다.

myMap.insert( std::map< int, MyClass >::value_type ( 1, MyClass(1) ) );
myMap.find( 1 )->second;

11
탁월한 대답 emplace-C ++ 11에서도 insert.
prideout

3
그 이유는 무엇 std::<map>::value_type거기에 insert전화?
thomthom

1
기본 생성자를 사용자 정의해야하는 이유는 무엇입니까?
schuess

@schuess 왜 그런지 모르겠습니다 : = default잘 작동해야합니다.
underscore_d

'지도에 해당 개체가 아직 포함되어 있지 않습니다'라는 조건이 런타임에 평가됩니다. 왜 컴파일 시간 오류입니까?
Gaurav Singh

7

예. STL 컨테이너의 값은 복사 의미 체계를 유지해야합니다. IOW, 그들은 기본 유형 (예 : int)처럼 행동해야합니다. 즉, 무엇보다도 기본 구성이 가능해야합니다.

이 (및 기타 요구 사항) 없이는 STL 컨테이너가 구현되는 데이터 구조에서 다양한 내부 복사 / 이동 / 스왑 / 비교 작업을 구현하는 것이 불필요하게 어려울 것입니다.

C ++ 표준을 참조하면 내 대답이 정확하지 않다는 것을 알 수 있습니다. 기본 구성은 실제로 요구 사항이 아닙니다 .

20.1.4.1부터 :

기본 생성자는 필요하지 않습니다. 특정 컨테이너 클래스 멤버 함수 서명은 기본 생성자를 기본 인수로 지정합니다. T ()는 잘 정의 된 표현식이어야합니다 ...

따라서 엄밀히 말해서 값 유형은 서명에서 기본 생성자를 사용하는 컨테이너의 함수를 사용하는 경우에만 기본 구성 가능해야합니다.

STL 컨테이너에 저장된 모든 값의 실제 요구 사항 (23.1.3)은 CopyConstructibleAssignable.

특정 컨테이너에 대한 기타 특정 요구 사항도 있습니다 Comparable(예 : 맵의 키).


덧붙여서, 다음은 comeau에서 오류없이 컴파일됩니다 .

#include <map>

class MyClass
{
public:
    MyClass(int t);
};

int main()
{
    std::map<int, MyClass> myMap;
}

따라서 이것은 g ++ 문제 일 수 있습니다.


2
bb가 [] 연산자와 관련하여 뭔가를 할 수 있다고 생각하십니까?
Nick Bolton

13
이 코드는 아마도 myMap []을 호출하지 않았기 때문에 컴파일 될 것입니다.
jfritz42 2011-08-30

3

stl :: map의 저장된 유형에 대한 요구 사항을 확인하십시오. 많은 stl 컬렉션에서는 저장 형식에 특정 속성 (기본 생성자, 복사 생성자 등)이 포함되어야합니다.

인수가없는 생성자는 stl :: map에 필요합니다. 왜냐하면 operator []가 아직 맵에 보관되지 않은 키로 호출 될 때 사용되기 때문입니다. 이 경우 operator []는 매개 변수없는 생성자를 사용하여 생성 된 새 키와 값으로 구성된 새 항목을 삽입합니다. 그리고이 새로운 값이 반환됩니다.


-2

다음 사항을 확인하십시오.

  • ';'를 잊었습니다. 클래스 선언 후.
  • 이에 따라 MyType이 선언되어야합니다.
  • 거기에 기본 생성자가 없습니다 ...

std :: map 선언이 올바른 것 같습니다.


기본 생성자를 추가하면 잘 컴파일됩니다.
Nick Bolton

-2

std :: pair가 필요하기 때문일 가능성이 높습니다. std :: pair는 값 의미 체계를 사용하여 두 개의 값을 보유하므로 매개 변수없이 인스턴스화 할 수 있어야합니다. 따라서 코드는 다양한 위치에서 std :: pair를 사용하여 호출자에게 맵 값을 반환하며 이는 일반적으로 빈 쌍을 인스턴스화하고 로컬 쌍을 반환하기 전에 값을 할당하여 수행됩니다.

map <int, smartptr <MyClass>>를 사용하는 스마트 포인터로이 문제를 해결할 수 있지만이 경우 널 포인터를 확인하는 오버 헤드가 추가됩니다.


2
+0. pair <T, U>는 기본 생성자가없는 타입 T와 U에서 잘 사용할 수 있습니다.이 경우 사용할 수없는 유일한 것은 pair <T, U>의 기본 생성자입니다. 적절한 품질의 map <K, V> 구현은 K와 V가 될 수있는 것을 제한하기 때문에이 기본 생성자를 사용하지 않습니다.
j_random_hacker
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.