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

大城市里の小女人 提交于 2019-12-08 18:28:45

问题


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

To prevent copying the whole data, I modify it to be std::vector<SomeStruct>& FindData(int key).
But, there will be no data for certain key, so sometimes I have nothing to return.
In that case, I declare a file scope variable that is an empty std::vector<SomeStruct> and return it.

But if I choose the pointer to vector, that is std::vector<SomeStruct>* FindData(int key) then I can just return NULL for non-existing key.

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

Code example are like: 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 normal std::vector.
Cons: Additional variable declared.

Pointer:
Pros: Shorter query function and no need other variable.
Cons: looks weird(?!), and you can't juse p[i], you have to (*p)[i], which is annoying.

Which one is better?


回答1:


You can also give the reference of output as a parameter, so that you can add some enumerator or bool result as a method output:

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



回答2:


It depends on your design requirements. If calling this function with an index that doesn't have a corresponding element is a programming error, then the code should abort. If it's a user error, it should throw an exception. If it's part of the expected usage, then you have three alternatives, again depending on your design. You can flag the problem, typically by returning a null pointer or returning a Boolean value from a function that takes a reference for the result. You can quietly return a newly created valid object, as std::set does. You can return a sentinel object that isn't part of your container, and users will have to check whether that's what they got before they use the returned value.




回答3:


If you don't mind creating new entries for unfound keys then you can use this code:

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

An alternative approach that avoids new entries for unfound 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;
}


来源:https://stackoverflow.com/questions/15714670/should-my-function-return-a-pointer-to-stdvector-or-a-reference-to-stdvecto

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!