Should my function return a pointer to std :: vector or a link to std :: vector?

I have std::map<int, std::vector<SomeStruct>> ,
and provide a query like std::vector<SomeStruct> FindData(int key) .

To prevent all data from being copied, I modify it as std::vector<SomeStruct>& FindData(int key) .
But for certain key data will not be, so sometimes I have nothing to return.
In this case, I declare a file scope variable, which is an empty std::vector<SomeStruct> and returns it.

But if I select a pointer to a vector, i.e. std::vector<SomeStruct>* FindData(int key) , then I can just return NULL for a nonexistent key .

Which one is better?
I found out that a pointer to std::vector bad (or weird? Not sure) in the question ( Is there any other syntax for this pointer operation? )
And I personally like the link to std::vector too, so I can use operator[] easier, but the disadvantage is that I have to declare an additional empty variable for it.

Code example: In SomeClass.h

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

Now in SomeClass.cpp :

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

Case 2:

 DataVec* FindDatas(int key) { DataMap::iterator It = m_DataMap.find(key); if (It == m_DataMap.end()) return NULL; return &(It->second); } 

Reference:
Pros: looks like a regular std::vector .
Cons: an additional variable is declared.

Pointer:
Pros: a shorter query function and no other variable.
Cons: it looks weird (?!) And you cannot juse p[i] , you need (*p)[i] , which is annoying.

Which one is better?

+6
source share
3 answers

You can also specify the link to the output as a parameter, so that you can add the result of the enumeration or bool as the output of the method:

  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
source

It depends on your design requirements. When calling this function with an index that does not have a corresponding element, there is a programming error, then the code should be interrupted. If this is a user error, it should throw an exception. If this is part of the intended use, then you have three alternatives, again depending on your design. You can point out a problem, usually by returning a null pointer or by returning a boolean from a function that accepts a link for the result. You can safely return the newly created valid object, as std::set does. You can return a watch object that is not part of your container, and users will need to check what they received before they return the return value.

+1
source

If you do not mind creating new entries for unreasonable keys, you can use this code:

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

An alternative approach that avoids new entries for unreasonable keys:

 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
source

All Articles