2013-03-30 15 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を返すことができます。

どちらが優れていますか?
私は
Is there other syntax for this pointer operation?)問題のstd::vectorへのポインタが悪い(または奇妙な?いないことを確認)であることを学んだし、あまりにも、私個人的にstd::vectorを参照するように、私は簡単にoperator[]を使用できるように、しかし欠点は、私は宣言する必要がありますそのための追加の空の変数。

コード例は次のようです: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]を怒らせることはできません。(*p)[i]には迷惑です。

どちらが優れていますか?

+0

リファレンスを返します。デフォルトの構築されたベクターは軽量のオブジェクトなので、追加の 'EmptyVector'を周りに置いても心配はありません。 'nullptr'を返すと、すべてのクライアントコードはそのチェックを含める必要があります。私は個人的に空のベクトルをチェックするよりも面倒です。 – Praetorian

+0

@Praetorian:私は同様の考えを持っていたので、私は参照を好む理由です。しかし、クライアントは 'if(p.empty())return'もチェックしなければならないので、ヌルチェックのような文がまだ存在するかもしれません:( –

答えて

0

あなたはunfoundキーに新しいエントリを作成する気にしないなら、あなたはこのコードを使用することができます:

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

unfoundキーに新しいエントリを避ける別のアプローチ:

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 [OK]を私は別の解決策を投稿しました – 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

あなたの設計要件によって異なります。対応する要素を持たないインデックスでこの関数を呼び出すのがプログラミングエラーである場合、コードは中止する必要があります。ユーザーエラーの場合は、例外がスローされます。予想される使用量の一部であれば、デザインに応じて3つの選択肢があります。通常、NULLポインタを返すか、結果の参照を取得する関数からブール値を返すことで、問題にフラグを立てることができます。 std::setのように、新しく作成された有効なオブジェクトを静かに返すことができます。コンテナの一部ではないセンチネルオブジェクトを返すことができます。返された値を使用する前に、そのコンテナの内容をチェックする必要があります。

関連する問題