C ++ Копировать данные, на которые указывает указатель

Я читатель давно, и первый раз плакат … Я искал долго и трудно найти ответ на то, что действительно невероятна свой ум прямо сейчас. Я должен что-то упустить, так как я считаю, что это должно работать …

Я пытаюсь создать класс данных, который будет содержать собственные копии переданных ему объектов. Я решил использовать std :: map для хранения этих данных. Смотрите пример кода ниже:

typedef std::map <std::string, myVar *> myVarContainer;

class myObj
{
public:
myObj(void);
virtual ~myObj(void);

void setVar(std::string Key, myVar & Var);

myVar * getVar(std::string Key);

void release()
{
for (myVarContainer::iterator i = VarContainer->begin(); i != VarContainer->end(); ++i)
{
delete (i->second);
}

VarContainer->clear();
};

myVarContainer * VarContainer;

};

typedef std::map <myVar, myObj *> myRow;

class myTable
{
public:
myTable(void);
virtual ~myTable(void);

void addDataPoint(myVar RowID, myVar ColID, myObj * Data)
{
std::map <myVar, myRow *>::iterator i = m_Rows->find(RowID);

if (i == m_Rows->end())
{
m_Rows->insert(make_pair(RowID, new myRow()));
}
i = m_Rows->find(RowID);

// i thought the below line would be creating a copy of the data?
// I thought this logic went:
// 1. create a new object copied from the value of 'Data'
// 2. return a pointer to this object and pair with the 'colID'
// 3. make this into a pair and insert into the main map
i->second->insert(make_pair(ColID, new myObj(*Data)));
};

protected:

std::map <myVar, myRow *> * m_Rows;
}int main()
{

myVar a, b, c, d;

myObj * o = new myObj();

o->setVar("test", a);
o->setVar("test2", b);

myTable * tab = new myTable();

myVar x1, y1, x2;

tab->addDataPoint(y1, x1, o);

o->release(); // this clears out both 'o' and the values in 'tab'!?!?

//at this point tab has no data in its object at y1,x1???

o->setVar("test3", c);
o->setVar("test4", d);

tab->addDataPoint(y1, x2, o);
}

Что я заметил, так это то, что мои данные были удалены слишком рано. Я полагаю, что что-то пропустил … Я думал, что создаю копию данных, на которые ссылается указатель, и затем сохраняю указатель нового экземпляра на моей карте … Есть мысли? Я ценю любую помощь!

1

Решение

Поэтому одной из проблем, связанных с использованием (владением) необработанных указателей в контейнерах, является то, что вам нужно вручную удалять экземпляры. Я предполагаю что myObj::~myObj делает это (выполняет итерацию, удаляя все элементы перед удалением самого контейнера).

Линия:

i->second->insert(make_pair(ColID, new myObj(*Data)));

Копировать конструирование myObj из данных.

К сожалению, поскольку вы не определяете конструктор копирования для myObj, компилятор сгенерирует его для вас, который просто скопирует указатель на VarContainer член. Он не создаст новую копию карты или что-либо, на что он ссылается внутри. После создания копии у вас есть два экземпляра, каждый из которых указывает на один и тот же контейнер, и оба экземпляра считают, что им принадлежит. Когда первый из них будет разрушен, он будет казаться нормальным, но фактически оставит другой экземпляр, указывающий на освобожденную память. Как только самый долгоживущий экземпляр попытается что-либо сделать с помощью этого указателя контейнера, произойдет что-то плохое.

Вы можете исправить это, сохраняя карты по значению, а не по указателю:

typedef std::map<std::string, myVar> myVarContainer;
typedef std::map<myVar, myObj> myRow;

Также изменить myObj::VarContainer быть нераспределенным членом. Это означает, что все теперь копируется правильно, и копия не будет ссылаться на что-либо из оригинала.

Обратите внимание, что вы также можете использовать умные указатели (такие как std::shared_ptr) вместо необработанных указателей, но вам все равно нужно быть осторожным с этим, поскольку, хотя копирование было бы безопасным, они обмениваются данными с оригиналом, что может не соответствовать вашим ожиданиям.

Вы должны взглянуть на следующее:

http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming)

0

Другие решения

Кажется, что вы действительно создаете копию объекта, но затем, когда вы отпускаете (), вы освобождаете VarContainer (удаляете все элементы и используете clear ()), поэтому копия, которую вы создали ранее (с копией указателя) , а не фактический контейнер) остается с указателем на пустой контейнер.

0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector