我在C ++中使用向量得到一些奇怪的行为我希望有人可以帮助我。我有一个这样的矢量:
vector<Instruction*> allInstrs;
指令的结构如下:
struct Instruction : simple_instr
{
InstrType type;
Instruction(const simple_instr& simple) : simple_instr(simple)
{
type = Simple;
loopHeader = false;
loopTail = false;
}
int Id;
bool loopHeader;
bool loopTail;
};
我遇到的问题是:
我需要迭代每条指令并提取特定字段并使用它们对向量中的指令进行一些分析。要做到这一点,我基本上是在做
VariableList Variables;
void GenerateVariableList()
{
for (int i = 0; i < allInstrs.size(); i++)
{
Variables.Add(allInstrs[i]);
}
Variables.RemoveDuplicates();
}
变量列表定义为
struct VariableList
{
void Add(simple_instr* instr)
{
PrintOpcode(instr);
switch(instr->opcode)
{
case STR_OP:
case MCPY_OP:
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
case LDC_OP:
Add(instr->u.ldc.dst);
break;
case BTRUE_OP:
case BFALSE_OP:
Add(instr->u.bj.src);
break;
case CALL_OP:
cout << "CALL OP" <<endl;
break;
case MBR_OP:
Add(instr->u.mbr.src);
break;
case RET_OP:
if (instr->u.base.src1 != NO_REGISTER)
Add(instr->u.base.src1);
break;
case CVT_OP:
case CPY_OP:
case NEG_OP:
case NOT_OP:
case LOAD_OP:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
break;
case LABEL_OP:
case JMP_OP:
break;
default:
Add(instr->u.base.dst);
Add(instr->u.base.src1);
Add(instr->u.base.src2);
break;
}
}
void Add(Variable var)
{
variableList.push_back(var);
}
void RemoveDuplicates()
{
if (variableList.size() > 0)
{
variableList.erase(unique(variableList.begin(), variableList.end()), variableList.end());
currentID = variableList.size();
}
}
VariableList()
{
currentID = 0;
}
VariableList(VariableList& varList, bool setLiveness = false, bool LiveVal = false)
{
currentID = 0;
for (int i = 0; i < varList.size(); i++)
{
Variable var(varList[i]);
if (setLiveness)
{
var.isLive = LiveVal;
}
variableList.push_back(var);
}
}
Variable& operator[] (int i)
{
return variableList[i];
}
int size()
{
return variableList.size();
}
vector<Variable>::iterator begin()
{
return variableList.begin();
}
vector<Variable>::iterator end()
{
return variableList.end();
}
protected:
int currentID;
vector<Variable> variableList;
void Add(simple_reg* reg, bool checkForDuplicates = false)
{ cout << "Register Check" <<endl;
if (reg == null)
{
cout << "null detected" << endl;
return;
}
if (reg->kind == PSEUDO_REG)
{
if (!checkForDuplicates || (checkForDuplicates && find(variableList.begin(), variableList.end(), reg->num) != variableList.end()))
{
cout << "Adding... Reg " << reg->num << endl;
Variable var(reg->num, currentID);
variableList.push_back(var);
currentID++;
}
}
}
};
当我这样做时,每条指令都转到默认的case语句,即使我知道一些指令不应该。如果我将GenerateVariableList更改为
void GenerateVariableList()
{
for (int i = 0; i < allInstrs.size(); i++)
{
PrintOpcode(allInstrs[i]);
Variables.Add(allInstrs[i]);
}
Variables.RemoveDuplicates();
}
所以除了Variables.Add中的第二个PrintOpCode之外,现在还有第二个PrintOpCode,程序运行正常。我无法理解为什么添加第二个PrintOpcode使其正常工作。所有打印操作码都是一个带有switch语句的函数,它只打印出一个特定的字符串,具体取决于simple_instr字段之一的值。
VariableList Variables包含在一个名为CFG
的单独结构中如果您需要更多信息/代码,我可以提供。如果答案显而易见,我道歉,我不经常用C ++编程
编辑:
其中一个答案,现在删除了,让我解决了。
以前我在做
static vector<Instruction*> ConvertLinkedListToVector(simple_instr* instructionList)
{
vector<Instruction*> convertedInstructions;
int count = 0;
for (simple_instr* current = instructionList; current; count++, current = current->next)
{
//Instruction* inst = new Instruction(*current);
Instruction inst = Instruction(*current);
inst.Id = count;
convertedInstructions.push_back(&inst);
}
return convertedInstructions;
}
制作矢量,但在阅读完答案之后,我将其改回使用“新”,现在它正常工作。谢谢你的帮助,对不起这个愚蠢的问题感到抱歉
答案 0 :(得分:1)
传递给构造函数的const simple_instr& simple
很可能超出了范围,并且保留了一个指向simple_instr的无效引用/指针。
答案 1 :(得分:1)
可能与你的问题无关,但肯定是一个奇怪的行为的潜在来源:当你不想要它时,你的Instruction(const simple_instr& simple)
构造函数可能会被调用。明确标明......
explicit Instruction(const simple_instr& simple) ...
如果这会导致编译器错误,那就是进展:-)您可能需要编写一个复制构造函数来使它们消失,并显式调用您需要的旧构造函数。
答案 2 :(得分:1)
所以,有几个可疑的观察结果:
VariableList
的定义中,您使用了名为Variable
的类型 - 该类型是如何定义的?for (vector<Intruction *>::iterator it = allInstrs.begin();
it != allInstrs.end();
++it) {
Variables.Add(*it);
}
boost::shared_ptr
或boost::ptr_vector
的向量而不是指针向量。答案 3 :(得分:0)
我可以向您概述与您的代码相关的“不应该”。
在这种情况下,你正确使用来自simple_instr的“派生”类,但是你做错了,因为稍后你会根据类型做一个switch语句。基于类型(而不是状态)的switch语句是反模式。您应该调用基类的一些虚方法。
您几乎肯定不希望派生类从基类复制。您希望使用参数构造它以构造其基类。
你想要一个基类指针的向量?并且管理生命周期可能是shared_ptr
常量-正确性。你的一些像size()这样的方法当然应该是const。对于其他人,您可能需要两次重载。