简体   繁体   中英

return a pointer of vector with shared_ptr

I am testing with the shared_ptr of vector. The purpose is simple, I want to return a pointer of vector and access the value in it. But it gives exception. "Unhandled exception at.. std:out_of_range at memory location ..". I am using Visual Studio 2012.

vector<int>* func()
{
    boost::shared_ptr<vector<int> > vec(new vector<int>());

    vec->push_back(123);
    return vec.get();
    }

int _tmain(int argc, _TCHAR* argv[])
{
    vector<int>* result = func();

    cout << result->at(0); // ERROR here
    return 0;
}

If you want to use shared pointers, then return a shared pointer, not a raw one. Otherwise, when the shared_ptr goes out of scope, it will destroy the vector. Accessing that vector will lead to undefined behaviour.

boost::shared_ptr<vector<int> > func()
{
    boost::shared_ptr<vector<int> > vec(new vector<int>());
    vec->push_back(123);
    return vec;
}

However, note that it's much better to return the vector by value:

vector<int> func()
{
    vector<int> vec;
    vec.push_back(123);
    return vec;
}

This way, there are no copies being made, either through move constructors or RVO .

The type you return from func() needs to be boost::shared_ptr<vector<int>> - not vector<int>* .

The whole point of shared pointers is you can pass them around as much as you like and when they all stop being referenced the memory they pointed to is reclaimed.

As you "forget" the reference to the shared pointer when you leave the function it will automatically reclaim the memory assigned at that point - leaving you with a pointer to an invalid memory location.

Your shared_ptr in your function is the only one referencing the pointer to your vector . When it goes out of scope (when the function returns), it therefore deletes the referenced pointer.

Make your function return a shared_ptr instead of a regular pointer.

I'd suggest you read up on how shared_ptr should be used, cause you're doing it all wrong.. It's meant to not having to deal with raw pointers anymore, definitely not mixing them. Basically you pass around the shared_ptr instance like you used to with raw pointers, but without having to care about deleting it anymore. Do this instead:

typedef std::vector< int > my_vector;
typedef boost::shared_ptr< my_vector > my_vector_ptr;

my_vector_ptr func()
{
  my_vector_ptr vec( boost::make_shared< my_vector >() );
  vec->push_back(123);
  return vec.get();
}

int _tmain(int argc, _TCHAR* argv[])
{
  my_vector_ptr result = func();
  cout << result->at(0);
  return 0;
}

Use back inserter to avoid mixing inserting and returning the same vector. Let the client specify witch type of vector it is ... thus making the function template-able.

code:

typedef std::vector< int > my_vector;
typedef boost::shared_ptr< my_vector > my_vector_ptr;

template <typename OutputIterator>
void func1(OutputIterator it)
{
   // std::copy (anotherVector.begin(), anotherVector.end(), it);
   *it++ = 123; 
}

void func2(my_vector& v)
{
   v.push_back(123);
}

int main()
{
    my_vector_ptr vec( new my_vector() );
    func1(std::back_inserter(*vec)); // func is now an algorithm .. 
    func2(*vec);
}

In func1 , the signature of the function says what this function does. You can't erase from vector, you can't do anything else, just what it says. Insert.

Think of func1 as an algorithm.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM