Копирование локального объекта в вектор

0

У меня есть одноэлементный класс, содержащий вектор с данными. Моя проблема в том, что я хочу добавить данные к этому вектору, используя стандартный метод push_back(). У меня есть объект, который я хочу сохранить в этом векторе, но это локальный объект (созданный в методе другого класса). Очевидно, что в конце этого метода локальная переменная будет удалена, что отлично, потому что я делаю push_back() этих данных для вектора.

Теперь это прекрасно работает, поскольку метод не заканчивается. После этого данные исчезли. Это кажется странным, потому что push_back() должен использовать конструктор копирования правильно? Теперь я попытался добавить локальную переменную в вектор по ссылке, по значению, как указатель и с конструктором перемещения в С++ 11, но все эти вещи не работают.

Итак, это настройка проблемы по классу:

  • ConnectionManager (удерживает вектор)
  • ClassA (который имеет метод с локальным объектом типаX)

Короче говоря, я хочу, чтобы объект, созданный в методе ClassA, был доступен после этого метода, но в векторе из класса ConnectionManager.

EDIT: Здесь типX, о котором я говорю:

struct Connection
{
    SOCKET socket;
    PlayerData* pPlayerData;
};

socket - это ваша обычная переменная SOCKET winsock, а PlayerData * - это настраиваемый объект, созданный с помощью Google ProtocolBuffer.

ДАЛЬНЕЙШЕЕ ИЗМЕНЕНИЕ:

Вот как я создаю данные:

Predefined::Connection connTemp;
connTemp.socket = 0;
connTemp.pPlayerData = data;
MultiplayerData::GetInstance()->AddPlayerToGame(connTemp);

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

  • 0
    Можете показать нам проблемный тип typeX ?
  • 0
    Я добавил это к основному вопросу
Показать ещё 13 комментариев
Теги:
c++11
vector

2 ответа

2

Если проблема заключается в том, что вы создаете данные PlayerData и ожидаете, что все эти же данные будут доступны после выхода функции, похоже, что вы должны использовать тип, например std::shared_ptr<PlayerData> а не голый PlayerData*.

#include <vector>
#include <memory>
//..
class PlayerData 
{
   int x, y, z;
   public:
     PlayerData(int a1, int a2, int a3) : x(a1), y(a2), z(a3) {}
};

typedef std::shared_ptr<PlayerData> PlayerDataPtr;

struct Connection
{
    SOCKET socket;
    PlayerDataPtr pPlayerData;
};

typedef std::vector<Connection> ConnectionVector;

void foo()
{
   auto data = std::make_shared<PlayerData>(1, 2, 3);  // create data dynamically
   //...
   Connection connTemp;
   connTemp.socket = 0;
   connTemp.pPlayerData = data;
   MultiplayerData::GetInstance()->AddPlayerToGame(connTemp);  // this does the push_back
   //...
}  

Поскольку pPlayerData теперь является shared_ptr, те копии, которые vector генерирует, просто увеличивают количество ссылок, и, наоборот, когда эти копии уничтожаются, счетчик ссылок уменьшается. Когда счетчик ссылок достигает 0, data действительно будут удалены.

Если вы не вызвали reset на общий указатель, это более или менее, ваша гарантия того, что data, созданные вами до push_back будут существовать, пока эта запись в векторе не будет удалена.

Кроме того, я отредактировал этот пример, чтобы показать более простой класс PlayerData. Обратите внимание, как используется make_shared.

  • 0
    Привет, спасибо за код. Я пробовал, но я получаю сообщение об ошибке: auto data = std::make_shared<PlayerData>(message.add_playerdata()); В нем говорится: 'PlayerData::PlayerData(const PlayerData &)' : cannot convert parameter 1 from 'PlayerData *' to 'const PlayerData &'
  • 0
    @Dries - Вам нужно показать, что возвращает message.add_playerdata() . Во-вторых, параметры make_shared - это параметры, которые вам нужны для создания PlayerData . Итак, вы говорите, что для создания PlayerData вам нужно передать указатель на PlayerData ? Это звучит странно, и, возможно, причина, по которой вы теряете данные. Посмотрите на мой отредактированный код выше.
Показать ещё 4 комментария
1

Соединение Struct действительно будет скопировано в вектор, поэтому вам не нужно беспокоиться о конце его жизни. Однако pPlayerData нужно указывать на память, выделенную новым и принадлежащую кому-то.

connTemp.pPlayerData = data;

Откуда берутся "данные" - генерируются локально? В какой-то момент "данные" должны быть выделены "новым".

Если "данные" уникальны, рассмотрите возможность использования auto_ptr или unique_ptr для типа члена pPlayerData. C++ не автоматически управляет стандартными указателями. Если они не уникальны, используйте shared_ptr или intrusive_ptr - можно начинать с совместного использования и дооснащения интрузивных позже.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню