2013-03-30 26 views
5

Ben std::map<int, std::vector<SomeStruct>>,
ve std::vector<SomeStruct> FindData(int key) gibi bir sorgu sağlarlar. İşlevi std :: vektörüne bir işaretçi mi, yoksa std :: vektörüne bir başvuru döndürüyor mu?

bütün veri kopyalama önlemek için, std::vector<SomeStruct>& FindData(int key) olmasını değiştirin.
Ancak, bazı key için veri olmayacak, bazen dönmek için hiçbir şeyim yok.
Bu durumda, boş bir std::vector<SomeStruct> dosya kapsam değişkenini bildirir ve döndürür.

Ancak, işaretçiyi vektöre seçtiğimde, std::vector<SomeStruct>* FindData(int key) ise key var olmayan için NULL döndürebilirim.

Hangisi daha iyi?
Ben operator[] kolay kullanabilmesi için std::vector bu işaretçi söz (Is there other syntax for this pointer operation?)
Ve şahsen çok std::vector atfen gibi kötü (veya garip? Emin) 'dir öğrenilen ama dezavantajı ı beyan etmek zorunda olduğu Bunun için ek bir boş değişken.

Kod örneği gibidir: SomeClass.h

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

Şimdi SomeClass.cpp yılında:

Durum 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; 
} 

Durum 2:

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

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

    return &(It->second); 
} 

bakın ence:
Artılar: normal std::vector gibi görünüyor.
Eksiler: Ek değişken beyan edildi.

İşaretçi:
Artılar: Daha kısa sorgu işlevi ve başka bir değişkene gerek yoktur.
Eksileri: (?!) garip görünüyor ve siz p[i] juse olamaz, sen can sıkıcı olduğu (*p)[i] gerekiyor.

Hangisi daha iyi?

+0

Bir başvuru döndürür; varsayılan bir yapılandırılmış vektör, hafif bir nesnedir, bu yüzden ek 'EmptyVector' etrafına sahip olmak endişe için herhangi bir neden olmamalıdır. Eğer 'nullptr' döndürürseniz, tüm istemci kodları için bir kontrol eklemem gerekecek, ki ben boş bir vektör için kontrol etmekten daha can sıkıcıyım. – Praetorian

+0

@Praetorian: Benzer bir düşüncem var, bu yüzden referans olmayı tercih ediyorum. Ancak istemcinin '(p.empty())' dönüşünü de kontrol etmesi gerekiyor, yani belki de null-check like ifadeleri hala var :( –

cevap

0

o zaman bu kodu kullanabilirsiniz hergün anahtarlar için yeni girdiler oluşturarak sakıncası yoksa:

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

hergün anahtarlar için yeni girdiler önler alternatif bir yaklaşım:

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

Merhaba: Varolan anahtarda ekstra giriş yapmak istemiyorum, teşekkürler! –

+0

@MarsonMao Tamam, alternatif bir çözüm gönderdim. – StackedCrooked

+0

FindDatas (non_existing_key) .push_back (blah) 'ı düşünün. (Aynı sorun orijinal kodda olsa da) –

1

yapabilirsiniz Ayrıca, bir parametre olarak çıkış referansı verir, böylece bir yöntem çıktısı olarak bazı numaralandırıcı veya bool sonucunu ekleyebilirsiniz:

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

Tasarım gereksinimlerinize bağlıdır. Bu işlevi karşılık gelen bir öğeye sahip olmayan bir dizinle çağırmak bir programlama hatasıysa, kod iptal edilmelidir. Bir kullanıcı hatasıysa, bir istisna atmalıdır. Beklenen kullanımın bir parçasıysa, yine tasarımınıza bağlı olarak üç alternatifiniz vardır.Sorunu, tipik olarak boş bir gösterici döndürerek veya sonuç için bir başvuru alan bir işlevden bir Boole değeri döndürerek işaretleyebilirsiniz. std::set'un yaptığı gibi yeni oluşturulmuş geçerli bir nesneyi sessizce döndürebilirsiniz. Kapsayıcınızın bir parçası olmayan bir sentinel nesnesini döndürebilir ve kullanıcıların döndürülen değeri kullanmadan önce sahip olduklarının olup olmadığını kontrol etmek zorunda kalacaklardır.

İlgili konular