Assigning std::vector to pointer inside a method

Viewed 100

I want to create a method, which uses std::vectors to build up a collection of data, then do some operations on the data and finally, I want to pass the generated information through a pointer of a given argument as seen in this small example:

struct MyStruct
{
    int* list;
    int entry_count;
};




static MyStruct createList()
{
   vector<int> vectorList;
   MyStruct data;

   vectorList.push_back(1);
   vectorList.push_back(1);
   vectorList.push_back(1);
   vectorList.push_back(1);
   vectorList.push_back(1);

   data.list = &vectorList.front();
   data.entry_count = vectorList.size();
   return data;
}

int main(int argc, char** argv)
{
   MyStruct data;
   data = createList();

   return 1;
}

The problem is, after the method is closed, the vector is destroyed and the pointer shows nowhere.

How will I able to handle this problem in the correct way? So how can I assign this collection to a pointer without de-allocating it?

3 Answers

You need to make the function local vectorList, static and use the std::vector::data for getting the underlying array via a pointer.

void createList(int* list)
{
   static std::vector<int> vectorList;
   // ...
   list = vectorList.data();
}

However, that makes vectorList to be the only instance in all of your createList function call. If you need different vectorList for different function call I would suggest wrapping all into a class.

#include <vector>

class MyList /* final */
{
   std::vector<int> mVectorList;

public:
   // operations via functions

   int* data() /* const noexcept */  // ---> provide a member to acces the underlying data
   {
      return mVectorList.data();
   }
};

You need to structure your code such that the owning std::vector outlives the scope in which any pointer into its buffer is used. Example:

void createList(std::vector<int>& storage, int *first)
{
    storage.push_back(42);

    first = storage.data();
}

// in main, or any function:

std::vector<int> storage;
int *first = nullptr;

createList(storage, first);

Here, we have passed storage as a reference (note &), hence any changes to it are made to the actual object created in the calling scope.

Note that it's crucial to remember that first might be an invalid reference once you alter storage, as std::vector might reallocate and move its buffer when upon adding new elements.

As per your use-case, if there is no need to create the vector initially, then you can follow the below approach.

#include <iostream>
#include <vector>

using namespace std;

int* createList()
{
    static std::vector<int> internalList;
    internalList.push_back(42);
    return internalList.data();
}


int main(int argc, char** argv)
{
    int *first = nullptr;
    first = createList();
    std::cout<<*first;

    return 0;
}

The approach is to declare a static vector and then return the pointer to the first element using the std::vector::data() method. For more reference follow the C++ Documentation

Related