我是一个非常新的程序员和超级初学者,所以我对c ++知之甚少。我特别提出了关于制作指针深层副本的问题。我所拥有的是一个充满POD的A类和一个指向这个类的指针(A * P)。 我有一个第二类B,其中包含一些其他POD和一个指向A类的指针向量。 我想填充这个A * P深拷贝的向量,因为在循环中我将动态分配和释放它。以下不起作用。我相信它是我的拷贝构造函数和=运算符的重载。这是我为了娱乐和学习而做的事情。
class A
{
public:
.....
.....
.....
};
class B
{
public:
B();
~B();
B(const B &Copier);
B& B::operator=(const B &Overloading);
vector<A*> My_Container;
A* Points_a_lot;
int counter;
};
B::B()
{
counter=0;
Points_a_lot=NULL;
}
B::~B()
{
for(size_t i=0; i<My_Container.size(); i++)
{
delete My_Container[i];
}
}
B::B(const B &Overloading)
{
My_Container[counter]=new A(*Overloading.Points_a_lot);
}
B& B::operator=(const B &Overloading)
{
if(!Overloading.My_Container.empty())
{
Overloading.My_Container[counter]=new B(*Overloading.Points_a_lot);
}
return *this;
}
int main()
{ A* p=NULL;
B Alphabet;
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
delete p;
}
return 0;
}
任何帮助都会很棒。我感谢你的时间。假设包含所需的库。
答案 0 :(得分:3)
好吧,在我看来,你对操作员应该做什么非常困惑。请查看operator overloading上的此页面。这应该可以帮助您开始使用该功能的正确途径。
其次,与您的问题无关,请查看this question,了解为什么您的字段(成员变量,您有什么)应该是私有的。
答案 1 :(得分:2)
您的代码中存在许多错误。主要的一点是你的赋值运算符和复制构造函数根本没有将vector
的指针深度复制到A
,而是试图将B*
放在一个位置。向量。你的赋值操作符应该做的是删除向量指向的元素,并在检查自我赋值后用源对象的向量指向的元素的深拷贝填充它。您的复制构造函数应该填充源对象元素的深层副本。
其次,您应该提供一个方法,将元素添加到类的向量中,并让它在内部设置计数器变量。必须在外部协调向量和计数器是容易出错的,并且OOP的一个优点是避免这种错误。但更好的是,完全删除counter
变量。你不需要它。然后,main
将被简化为:
int main()
{
B Alphabet;
for(....)
{
A* p = new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.appendElement(p); // B takes ownership, no need to delete in main
}
}
和appendElement
可能是
class B
{
public:
void appendElement(A* element) { myContainer_.push_back(element); }
// other public methods
private:
std::vector<A*> myContainer_;
};
您可以通过存储某种单一所有权智能指针而不是原始指针来进一步改善这一切。这意味着您不必担心自己删除。但这可能超出了这个问题的范围。
现在,您应该考虑完全避免使用指针。在这种情况下,您必须不提供复制构造函数,赋值运算符或析构函数。编译器合成的会做得很好。你的B级减少到
class B
{
public:
void appendElement(const A& element) { myContainer_.push_back(element); }
// other public methods
private:
std::vector<A> myContainer_;
};
答案 2 :(得分:1)
我并不完全明白您的要求是什么,因此我尝试修复代码并执行B
的深层复制,因为这似乎是您所要求的。
#include <vector>
using namespace std;
class A
{
public:
A() : m_someInt(0), m_someFloat(0.0f) {}
// Redundant but putting it here for you to see when it is called (put break-point)
A(const A& a_other)
{
m_someInt = a_other.m_someInt;
m_someFloat = a_other.m_someFloat;
}
int m_someInt;
float m_someFloat;
};
class B
{
public:
B();
~B();
B(const B &Copier);
B& B::operator=(const B &Overloading);
void Cleanup();
void AddA(const A* a);
private:
vector<A*> My_Container;
A* Points_a_lot;
};
B::B()
{
Points_a_lot=NULL;
}
B::~B()
{
Cleanup();
}
B::B(const B &Overloading)
{
// Deep copy B
operator=(Overloading);
}
B& B::operator=(const B &Overloading)
{
// Delete old A's
Cleanup();
// Not using iterators to keep it simple for a beginner
for (size_t i = 0; i < Overloading.My_Container.size(); ++i)
{
// We need new A's which will then copy from the A's in Overloading's container
A* newA = new A( *(Overloading.My_Container[i]) );
// Done with allocation and copy, push_back to our container
My_Container.push_back(newA);
}
return *this;
}
void B::Cleanup()
{
// Assuming B is not responsible for cleaning up Points_a_lot
Points_a_lot = NULL;
for (size_t i = 0; i < My_Container.size(); ++i)
{
delete My_Container[i];
}
// Automatically called when My_Container is destroyed, but here we
// are open to the possibiliy of Cleanup() being called by the client
My_Container.clear();
}
void B::AddA(const A* a)
{
// We are adding a new A. In your code, the incoming A is going to
// be destroyed, therefore, we need to allocate a new A and copy
// the incoming A
A* newA = new A(*a);
My_Container.push_back(newA);
}
int main()
{
A* p=NULL;
B Alphabet;
for(int i = 0; i < 10; ++i)
{
p = new A();
//some stuff example p->Member_of_A=3; etc..
Alphabet.AddA(p);
delete p;
}
// If you put a breakpoint here and step through your code, you will see
// `B` deep-copied
B NewAlphabet = Alphabet;
return 0;
}
一些注意事项:
New
和delete
A
是一个坏主意。我知道你这样做只是为了学习,这很好,但你可能想要牢记这一点。不要通过A
销毁p
,而是允许B
取得新A
答案 3 :(得分:0)
看起来你应该让你的My_Container由unique_ptrs组成,这样当你分配时,vector会接管A实例的所有权
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
delete p;
}
所以改为将My_Container声明为
vector<std::unique_ptr<A*> > My_Container;
然后代码将
for(....)
{
p=new A;
//some stuff example p->Member_of_A=3; etc..
Alphabet.My_Container[Alphabet.counter]=p;
Alphabet.counter++;
}
然后,如果你需要做一个'深层复制',在A中创建一个名为clone()的东西,然后将unique_ptr
返回给实例,当你需要创建一个副本时使用它。
答案 4 :(得分:0)
您可能需要查看boost::ptr_vector
。它的接口与std::vector
的接口非常相似,但它是针对指针而定制的,因此:
为了使副本生效,您必须提供A* new_clone(A const*)
实施。