Назначение std :: vector указателю внутри метода - PullRequest
2 голосов
/ 11 июля 2020

Я хочу создать метод, который использует std::vector s для создания коллекции данных, затем выполняет некоторые операции с данными и, наконец, я хочу передать сгенерированную информацию через указатель данного аргумента, как показано в этом небольшом примере:

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

Проблема в том, что после закрытия метода вектор уничтожается и указатель нигде не показывает.

Как я смогу решить эту проблему в правильный путь? Итак, как я могу назначить эту коллекцию указателю, не освобождая ее?

Ответы [ 3 ]

2 голосов
/ 11 июля 2020

Вам нужно сделать функцию локальной vectorList, static и использовать std::vector::data для получения базового массива через указатель.

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

Однако это делает vectorList единственным экземпляром во всех вызовах функции createList. Если вам нужны разные vectorList для разных вызовов функций, я бы предложил обернуть все в класс.

#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();
   }
};
1 голос
/ 11 июля 2020

В соответствии с вашим вариантом использования, если нет необходимости изначально создавать вектор, вы можете использовать следующий подход.

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

Подход состоит в том, чтобы объявить вектор stati c и затем верните указатель на первый элемент, используя метод std::vector::data(). Для получения дополнительной информации см. Документация C ++

1 голос
/ 11 июля 2020

Вам необходимо структурировать свой код таким образом, чтобы владелец std::vector пережил область, в которой используется любой указатель на его буфер. Пример:

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

Здесь мы передали storage как ссылку (примечание &), поэтому любые изменения в нем вносятся в фактический объект, созданный при вызове область.

Обратите внимание: важно помнить, что first может быть недопустимой ссылкой после изменения storage, поскольку std::vector может перераспределить и переместить свой буфер при добавлении новых элементов.

...