2013-03-30 2 views
5

나는 std::map<int, std::vector<SomeStruct>>,
을 가지고 있으며 std::vector<SomeStruct> FindData(int key)과 같은 쿼리를 제공합니다.내 함수가 std :: vector에 대한 포인터 또는 std :: vector에 대한 참조를 반환해야합니까?

데이터 전체를 복사하지 않으려면 std::vector<SomeStruct>& FindData(int key)으로 수정하십시오.
그러나 특정 데이터는 없습니다 key, 그래서 때로는 아무것도 반환 할 수 있습니다.
그런 경우, 파일 범위 변수를 선언하고 빈 std::vector<SomeStruct>을 반환합니다.

그러나 벡터에 대한 포인터를 선택하면 std::vector<SomeStruct>* FindData(int key)이되며 key에 대해 NULL을 반환 할 수 있습니다.

어느 것이 더 낫습니까?
은 내가 operator[] 쉽게 사용할 수 있도록 std::vector에 그 포인터, 질문 (Is there other syntax for this pointer operation?)
그리고 개인적으로 너무 std::vector을 참조 같은 나쁜 (또는 이상한?하지 않도록)입니다 배웠습니다,하지만 단점은 내가 선언 할 필요가있다 그것에 대한 추가 빈 변수.

코드 예제 등이있다 : SomeClass.h

typedef std::vector<SomeStruct> DataVec; 
typedef std::map<int, DataVec> DataMap; 
DataMap m_DataMap; 

지금 SomeClass.cpp에서 :

사례 1 :

namespace 
{ 
    DataVec EmptyVector; 
} 

DataVec& FindDatas(int key) 
{ 
    DataMap::iterator It = m_DataMap.find(key); 

    if (It == m_DataMap.end()) return EmptyVec; 

    return It->second; 
} 

사례 2 :

DataVec* FindDatas(int key) 
{ 
    DataMap::iterator It = m_DataMap.find(key); 

    if (It == m_DataMap.end()) return NULL; 

    return &(It->second); 
} 

참조 ence :
장점 : 보통 std::vector처럼 보입니다.
단점 : 추가 변수가 선언되었습니다.

포인터 :
장점 : 쿼리 함수가 짧고 다른 변수가 필요하지 않습니다.
단점 : 이상하게 보입니다 (?!), p[i]을 사용하면 +1 할 수 있습니다. (*p)[i], 귀찮습니다.

어느 것이 더 낫습니까?

+0

참조를 반환합니다. 디폴트의 ​​생성 된 벡터는 가벼운 객체이므로 주위에 추가로'EmptyVector'를두면 걱정할 필요가 없습니다. 'nullptr'을 리턴하면 모든 클라이언트 코드는 그 체크를 포함해야합니다. 나는 빈 vector를 검사하는 것보다 개인적으로 더 짜증이납니다. – Praetorian

+0

@Praetorian : 나는 비슷한 생각을 가지고 있습니다. 그래서 나는 참조를 선호합니다. 하지만 클라이언트는'if (p.empty()) return '을 검사해야하기 때문에 null 체크 문이 여전히 존재할 수도 있습니다 : ( –

답변

0

당신은 당신이 코드를 사용할 수 있습니다 발견되지 않은 키에 대한 새 항목을 작성 괜찮다면 :

DataVec& FindDatas(int key) 
{ 
    return m_DataMap[key]; 
} 

발견되지 않은 키에 대한 새 항목 피할 다른 방법 :

DataVec& FindDatas(int key) 
{ 
    DataMap::iterator It = m_DataMap.find(key);  
    if (It == m_DataMap.end()) { 
     // created on first unfound key and stays 
     // alive until the end of the program 
     static DataVec fEmpty; 
     return fEmpty; 
    }  
    return It->second; 
} 
+0

안녕 : 존재하지 않는 키에 추가 항목을 추가하고 싶지 않습니다. 감사합니다! –

+0

@MarsonMao 좋아요, 대체 솔루션을 게시했습니다. – StackedCrooked

+0

'FindDatas (non_existing_key) .push_back (blah)'를 고려하십시오. (원래 코드에도 같은 문제가 있습니다) –

1

당신은 할 수 있습니다 또한 출력 결과를 매개 변수로 제공하여 메서드 출력으로 일부 열거 자 또는 부울 결과를 추가 할 수 있습니다.

namespace 
    { 
     DataVec EmptyVector; 
    } 

    bool FindDatas(int key, DataVec& output) 
    { 
     DataMap::iterator It = m_DataMap.find(key); 

     if (It == m_DataMap.end()) return false; 

     output = It->second; 
        return true; 
    } 
1

디자인 요구 사항에 따라 다릅니다. 해당 요소가없는 인덱스로이 함수를 호출하면 프로그래밍 오류가 발생하므로 코드가 중단되어야합니다. 사용자 오류 인 경우 예외가 발생합니다. 예상 사용량의 일부인 경우 디자인에 따라 세 가지 대안이 있습니다.일반적으로 널 포인터를 리턴하거나 결과에 대한 참조를 취하는 함수에서 부울 값을 리턴하여 문제점을 플래그 할 수 있습니다. std::set처럼 새롭게 생성 된 유효한 객체를 조용히 반환 할 수 있습니다. 컨테이너의 일부가 아닌 감시 객체를 반환 할 수 있으며, 사용자는 반환 값을 사용하기 전에 그 객체가 가져온 객체인지 여부를 확인해야합니다.

관련 문제