[英]C++ Copy data pointed at by pointer
I'm a long-time reader, and first-time poster... I've searched long and hard to find an answer to something that's really boggling my mind right now. 我是一个长期的读者,也是一个第一次的发帖人...我已经搜寻了很长时间,并且很难找到答案,这些答案现在真的让我很困惑。 I must be missing something, as I believe this should work...
我一定想念一些东西,因为我相信这应该起作用。
I'm trying to create a datatable class that will contain it's own copies of the objects passed to it. 我正在尝试创建一个数据表类,其中将包含它自己的传递给它的对象的副本。 I've decided to use std::map's to contain this data.
我决定使用std :: map包含此数据。 See the example code below:
请参见下面的示例代码:
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);
}
What I'm noticing is that my data is deleted too early. 我注意到的是我的数据删除得太早了。 I believe I've missed something... I had thought I was creating a copy of the data referenced by the pointer and then storing a newly instance'd pointer in my map... Any thoughts?
我相信我错过了一些事情……我以为我正在创建指针引用的数据的副本,然后将新实例引用的指针存储在地图中……有什么想法吗? I appreciate any help!
感谢您的帮助!
似乎您确实在创建对象的副本,但是当您释放()时,您将释放VarContainer(删除所有项目并使用clear()),因此,您之前创建的副本(带有指针的副本) ,而不是实际的容器)留有指向空容器的指针。
So one of the problems that using (owning) raw pointers in containers is that you need to manually delete the instances yourself. 因此,在容器中使用(拥有)原始指针的问题之一是您需要自己手动删除实例。 I presume that
myObj::~myObj
does just that (iterates the container deleting all elements before deleting the container itself). 我认为
myObj::~myObj
就是这样做的(在删除容器本身之前,先迭代容器删除所有元素)。
The line: 该行:
i->second->insert(make_pair(ColID, new myObj(*Data)));
Is copy constructing a myObj from Data. 正在从Data复制构造myObj。
Unfortunately, because you are not defining a copy constructor for myObj the compiler will generate one for you which will just copy the pointer to the VarContainer
member. 不幸的是,由于您没有为myObj定义复制构造函数,因此编译器将为您生成一个复制构造函数,它将仅将指针复制到
VarContainer
成员。 It won't create a new copy of the map or anything that it refers to internally. 它不会创建地图或其内部引用的任何内容的新副本。 Once a copy is created you then have two instances which both point to the same container and both instances think that they own it.
创建副本后,您将拥有两个都指向同一个容器的实例,并且两个实例都认为它们拥有它。 When the first one gets destructed it will seem to ok but actually leaves the other instance pointing to freed memory.
当第一个实例被破坏时,它看起来还可以,但实际上却使另一个实例指向了已释放的内存。 As soon as the longest lived instance tries to do anything using this container pointer something bad will happen.
寿命最长的实例一旦尝试使用此容器指针执行任何操作,就会发生问题。
You could fix this by storing the maps by value and not by pointer: 您可以通过按值而不是按指针存储映射来解决此问题:
typedef std::map<std::string, myVar> myVarContainer;
typedef std::map<myVar, myObj> myRow;
Also change myObj::VarContainer
to be a non-allocated member. 还要将
myObj::VarContainer
更改为未分配的成员。 This means that everything now gets copied correctly and a copy will not reference anything from the original. 这意味着现在可以正确复制所有内容,并且副本不会引用原始内容。
Note that you can also use smart pointers (such as std::shared_ptr
) instead of raw pointers but you will still need to be careful with that as, although copying would be safe, they share data with the original which might not be what you expect. 请注意,您还可以使用智能指针(例如
std::shared_ptr
)来代替原始指针,但您仍需要注意这一点,因为尽管复制是安全的,但它们会与原始指针共享数据,而这可能与您不期望。
You should take a look at the following: 您应该查看以下内容:
http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming ) http://en.wikipedia.org/wiki/Rule_of_three_(C%2B%2B_programming )
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.