我有以下两个类: 第一个
class node{
public:
node(); //default constructor
node(const node&);//copy constructor
~node(); //destructor
node& operator= (const node&);
short visits;
bool inizpc;
cards cards_first;
cards cards_second;
cards * first; //cards is another class, don't mind that
cards * second;
int * suits;
node * children;
//other members
}
和班级
class tree{
public:
tree() : //initialization list {branch.reserve(20)};//constructor
tree(const tree&); //copy constructor
~tree();//destructor
tree& operator= (const tree&);
std::vector<node> branch;
//other members
void tries(node&);
}
当我尝试使用分支向量时出现问题,特别是当我在以下函数中使用.push_back()函数时
void tree::tries(node& a){
a.visits++;
branch.push_back(a);
}
编译器只是在不运行它的情况下终止该函数。问题是branch.push_back
,但我没有使用向量,所以我没有得到错误的立场和我所缺少的。另外,push_back如何分配我传递的对象?它会调用复制构造函数吗?
~node(){
cout << "deleting node\n";
delete[] first;
delete[] second;
delete[] suits;
delete[] children;
}
我尝试过像
这样的事情node a;
a.visits=1;
cout << a.visits;
注释掉析构函数定义和声明它工作正常。是否有理由在执行结束前将其删除?
另外,这里是默认构造函数,复制构造函数和复制分配定义,析构函数如上所定义
//default constructor
node::node():
visits(0),
inizpc(false)
cards_first(0,0);//cards have a parameter ctor
cards_second(0,0);
{
first=new carte[10];
second=new carte[10];
suits=new short[4];
children=new node[visits];
}
//copy constructor
node::node(node& a){
visits=a.visits;
inizpc=a.inizpc;
cards_first=a.cards_first;
cards_second=a.cards_second;
first=new cards[10];
for(int i=0; i<10; i++) first[i]=a.first[i];
second=new cards[10];
for (int i=0; i<10; i++) second[i]=a.second[i];
suits=new int[4];
for(int i=0; i<4; i++) suits[i]=a.suits[i];
children=new node[a.visits];
for (int i=0; i<a.visits; i++) children[i]=a.children[i];
}
//assignement
node& node::operator= (node& a){
visits=a.visits;
inizpc=a.inizpc;
cards_first=a.cards_first;
cards_second=a.cards_second;
delete[] first;
first=new cards[10];
for(int i=0; i<10; i++) first[i]=a.first[i];
delete[] second;
second=new cards[10];
for (int i=0; i<10; i++) second[i]=a.second[i];
delete[] suits;
suits=new int[4];
for(int i=0; i<4; i++) suits[i]=a.suits[i];
delete[] children;
children=new node[a.visits];
for (int i=0; i<a.visits; i++) children[i]=a.children[i];
}
答案 0 :(得分:2)
鉴于您发布了复制构造函数析构函数,您的赋值运算符未实现。相反,您发布的内容看起来像是复制构造函数和赋值运算符的组合。
在您的原始帖子中,您确实没有实现赋值运算符。我不知道你是否匆匆发布了你的课程,只是忘了发布它,但无论如何,你需要这个功能才能完成rule of 3。
正如我的评论所暗示的那样,缺少node
等类的赋值运算符会在某个时刻咬住你,无论是现在还是以后 - 你都无法避免它。
要正确编写赋值运算符,使用copy / swap idiom是最容易的事情,因为你有一个似乎正确处理的复制构造函数和析构函数:
#include <algorithm>
node& operator=(const node& a)
{
node temp(a);
std::swap(temp.visits, visits);
std::swap(temp.inizpc, initzpc);
std::swap(temp.cards_first, cards_first);
std::swap(temp.cards_second, cards_second);
std::swap(temp.first, first);
std::swap(temp.second, second);
std::swap(temp.suits, suits);
std::swap(temp.children, children);
return *this;
}
我们所做的只是创建一个临时的,用临时的交换出当前对象的内部,并让临时死在最后用旧数据。另请注意,返回引用。
这种技术只有在复制构造函数和析构函数完美且复制构造函数不使用赋值运算符作为辅助函数时才有效(不幸的是,一些C ++程序员似乎坚持这样做)。再一次,看一下你的代码,似乎这两个函数都是正确编写的,因此赋值操作符的复制/交换将是完成这项工作的最佳方法。
执行此操作后,您应该在一个简单的node
程序中彻底测试main
类。您不需要std::vector
来测试您的类是否具有正确的复制语义:
int main()
{
node n1;
// assume that n1 has been populated with some data
//...
node n2 = n1;
node n3;
n3 = n1;
}
一个小的main
函数测试复制构造,赋值和销毁。如果有任何故障,上述程序将出现故障。上面的程序应该能够从头到尾运行,没有内存错误,没有内存泄漏,没有双重释放等等。
此外,您的tree
类不需要析构函数,赋值运算符或复制构造函数。您应该删除它们,因为tree
包含所有可安全复制的成员(现在可以正确复制node
类,因为它现在具有正确的复制语义)。