Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Returning a std::vector - right approach

Tags:

c++

stl

vector

I am trying to create a class method that will return a std::vector, and am a bit confused about the best way to do this.

The approach I've used is to define the following method:

std::vector<double>* GetBins(void);

and in the method, allocate a new std::vector, which I fill with data. I'm returning a pointer to this ie.

std::vector<double>* Frequency::GetBins(void) {
    std::vector<double> *rtnVec = new std::vector<double>();
    for (_itMap = _mapFreq.begin(); _itMap != _mapFreq.end(); _itMap++ ) {
        rtnVec->push_back((*_itMap).first);
    }
    return rtnVec;
 }

(_itMap is a class-defined iterator).

In my main.cpp, I've done the following:

 std::vector<double>* myBins;
 myBins = myFreq3->GetBins();
 delete myBins;

I know with this approach, I'm going to get a dangling pointer unless I delete the pointer in the main.cpp code, so it's already a bit 'dangerous'. What's the best way to return a new std::vector from a class method?

Thanks guys Pete

like image 679
Pete855217 Avatar asked Apr 19 '13 13:04

Pete855217


2 Answers

The best way is to return by value:

std::vector<double> Frequency::GetBins() {
    std::vector<double> rtnVec;
    rtnVec.reserve(_mapFreq.size()); // reserve enough size, no reallocations
    for (_itMap = _mapFreq.begin(); _itMap != _mapFreq.end(); ++_itMap ) {
        rtnVec.push_back(_itMap->first);
    }
    return rtnVec;
}

Then you'd use the function like this:

std::vector<double> myBins = myFreq3->GetBins();
// no need for delete!

The compiler will probably use RVO and perform no copies. If you're using C++11, then move semantics will ensure that no copies are performed.

like image 97
mfontanini Avatar answered Oct 08 '22 00:10

mfontanini


Return by value

std::vector<double> Frequency::GetBins(void) {
    std::vector<double> rtnVec;

    // ...

    return rtnVec;
 }

However if you want return by pointer, you can use smart pointers:

std::unique_ptr<std::vector<double>> Frequency::GetBins(void) {
    std::unique_ptr<std::vector<double>> rtnVec(new std::vector<double>());

    //...

    return rtnVec;
 }
like image 27
masoud Avatar answered Oct 08 '22 00:10

masoud