我是这里的新用户,这是我的第一个问题,所以请不要苛刻地评判我。我不仅在这个网站上,而且在其他网站上也检查了许多类似的问题。但我没有找到答案。
问题是使用指针创建复制构造函数。对于那些可能会问:为什么需要指针?的人:我有一个类stmt
,其中包含vector<stmt>
,它将允许我构造树状数据结构。然后,我将执行一些函数来更改 stmt 参数的值。没有指针,它们不会改变
它编译,但随后给出异常未处理(运行时错误(
我的第一个尝试看起来像这样:
struct stmt
{
string lexeme;
int *size;
int *lay;
bool *nl;
vector<stmt>* follow;
stmt(string l)
{
lexeme = l;
size = new int;
*size = l.size()+2;
lay = new int;
*lay = 0;
nl = new bool;
*nl = false;
follow = new vector<stmt>;
}
stmt(const stmt &s)
{
lexeme = s.lexeme;
size = new int; //Crashes here : Unhandled exception:std::length_error at memory location ...
*size = *s.size;
lay = new int;
nl = new bool;
follow = new vector<stmt>;
follow = s.follow;
}
};
第二次我也尝试了这个:
stmt(const stmt &s)
:lexeme.(s.lexeme), size (s.size), ......and so on
{}
不幸的是,这也无济于事。
所以,这是我的第三次尝试,但没有帮助
重要提示:我注意到当我尝试使用返回类型为stmt
的函数在另一个stmt
的向量中创建和emplace_back
新的stmt
元素时,就会发生这种情况。
下面是一个表示关键问题的代码:
stmt Program("Program");
stmt ParseRelop(string p);
void EMP(stmt s)
{
s.follow->push_back(ParseRelop("token"));
}
stmt ParseRelop(string p)
{
stmt s(p);
return s;
}
int main()
{
EMP(Program);
cout<<Program.follow->at(0).lexeme;
}
像这样
stmt(const stmt &s)
{
...
follow = new vector<stmt>(*s.follow);
}
此版本通过从复制的对象复制向量来分配新向量(*s.follow
是复制对象中的向量(。
您的版本分配了一个新指针,但随后用复制对象的指针副本覆盖了它。
您要复制矢量,而不是指向矢量的指针。
您应该对其他指针使用相同的技术
size = new int(*s.size);
lay = new int(*s.lay);
等。
让我们首先使您的stmt
类副本正确。 一旦你这样做了,那么问题将来自代码的其他部分,这些部分不涉及stmt
泄漏内存或访问无效内存:
#include <vector>
#include <string>
#include <algorithm>
struct stmt
{
std::string lexeme;
int *size;
int *lay;
bool *nl;
std::vector<stmt>* follow;
// Constructor. Note the usage of the member initialization list
stmt(std::string l) : lexeme(l), size(new int), lay(new int(0)), nl(new bool(false)),
follow(new std::vector<stmt>())
{
*size = l.size() + 2;
}
// Copy constructor. Note that we use the member initialization list,
// and copy all the members from s to the current object, not partial copies
stmt(const stmt &s) : lexeme(s.lexeme), size(new int(*s.size)), nl(new bool(*s.nl)),
lay(new int(*s.lay)), follow(new std::vector<stmt>(*s.follow))
{}
// The assignment operator. Note that we use copy / swap to swap out
// all the members, and that a check for self-assignment is done.
stmt& operator=(const stmt &s)
{
if (this != &s)
{
stmt temp(s);
std::swap(lexeme, temp.lexeme);
std::swap(size, temp.size);
std::swap(lay, temp.lay);
std::swap(nl, temp.nl);
std::swap(follow, temp.follow);
}
return *this;
}
// The destructor destroys all the memory
~stmt()
{
delete size;
delete lay;
delete nl;
delete follow;
}
};
这个类现在正确地遵循了 3 的规则,并且应该是可安全复制的。 我在注释中输入了每个函数的作用,您应该研究为什么该类现在应该正常工作。
我不想深入太多,因为实际上你不会有指向int
、bool
甚至vector<stmt>
的指针。
引用:
法则 3
复制/交换成语