所以我有一些SegFaults,并想知道是否有人可以更深入地解释我这是如何工作的。
我有一个围绕数字变量的包装类,我正在尝试构建表达式的计算树。以下是示例代码:
class DoubleWrap{
public:
static int id;
DoubleWrap(double value){this->value = value;myid=++id;}
double value;
int myid;
std::vector<DoubleWrap*> parents;
DoubleWrap operator+(DoubleWrap& x){
DoubleWrap result(this->value + x.value);
setParents(*this,result);
setParents(x,result);
return result;
}
void setParents(DoubleWrap& parent,DoubleWrap& child){
child.parents.push_back(&parent);
}
void printTree(){
std::cout<< "[" << this->myid << "]-(";
for (auto& elem: this->parents)
std::cout<< elem->myid << "," << elem <<",";
std::cout<<")"<<std::endl;
for (auto& elem: this->parents)
elem->printTree();
}
}
我得到的问题是x = a + b + c + d这样的表达式;当我试图寻找x的父母时,它有2个父母,但父母[0] .parents [0]是零,例如由于某种原因,指向分配位置的指针不起作用或分配的内存被销毁?
我很感兴趣,如果有人可以告诉我一个解决方法以及为什么会这样。
举一个关于这段代码的例子:
DoubleWrap dw(12.6);
DoubleWrap dw2(12.5);
DoubleWrap dw3(12.4);
DoubleWrap dw4(12.3);
DoubleWrap a = dw + dw2 + dw3;
DoubleWrap b = a + dw+ dw2+ dw3 + dw4;
b.printTree();
我期待输出:
[10]-(9,0x13a4b50,4,0x7fff5bdb62f0,)
[9]-(8,0x13a4b00,3,0x7fff5bdb62c0,)
[8]-(7,0x13a49f0,2,0x7fff5bdb6290,)
[7]-(6,0x7fff5bdb6320,1,0x7fff5bdb6260,)
[6]-(5,0x13a4db0,3,0x7fff5bdb62c0,)
[5]-(1,0x7fff5bdb6260,2,0x7fff5bdb6290,)
[1]-()
[2]-()
[3]-()
[1]-()
[2]-()
[3]-()
[4]-()
但我得到的结果(通常在不同的运行中有所不同):
[10]-(9,0x7ffffd5e2f00,4,0x7ffffd5e2de0,)
[9]-(33,0x1c6da10,3,0x7ffffd5e2db0,)
Process finished with exit code 139
我的猜测是,运算符的返回实际上复制了DoubleWrap变量,因此父指针中的指针指向的值超出了范围而内存被释放了?
临时解决方案是通过引用返回,但问题是为什么并且有适当的解决方案?
PS:修复了我之前遇到的错误,这在setParents中是个错误。
答案 0 :(得分:1)
您的问题是您正在向临时对象添加指向该向量的指针。
DoubleWrap a = dw + dw2 + dw3;
以上内容将首先调用dw.operator+(dw2)
。这会创建一个临时对象,我们将其命名为temp
。然后它会调用temp.operator+(dw3)
。现在在operator+
内,此setParents
号调用temp
作为parent
。然后,您获取temp
的地址(至少这是代码应该进行编译的内容)并将其添加到child
的向量中。
现在,当operator+
的调用返回时,temp
被破坏,a
中的向量包含指向不存在对象的指针。
您可以使用shared_ptr
将元素存储在向量中来解决此问题。请注意,如果参考周期是可能的,您应该小心使用weak_ptr
打破这些周期(我在下面的代码中没有包含实现)。这是最终代码的样子:
class DoubleWrap {
public:
static int id;
DoubleWrap(double value) : value(value), myid(++id) {}
double value;
int myid;
std::vector<std::shared_ptr<DoubleWrap>> parents;
DoubleWrap operator+(const DoubleWrap& x) const {
DoubleWrap result(this->value + x.value);
setParents(*this, result);
setParents(x, result);
return result;
}
static void setParents(const DoubleWrap& parent, DoubleWrap& child) {
child.parents.push_back(std::make_shared<DoubleWrap>(parent)); // makes a copy of parent
}
void printTree() const {
std::cout << "[" << this->myid << "]-(";
for (const auto& elem: this->parents)
std::cout << elem->myid << "," << elem.get() << ",";
std::cout << ")" << std::endl;
for (const auto& elem: this->parents)
elem->printTree();
}
};
int DoubleWrap::id = 0;
答案 1 :(得分:0)
您的代码: DoubleWrap运算符+(DoubleWrap&amp; x){ DoubleWrap结果(this-&gt; value + x-&gt; value); 如果x是一个指向DoubleWrap类的指针,但你已经将x编码为DoubleWrap类对象而不是指针,那么你的代码是正确的 应该读 : DoubleWrap运算符+(DoubleWrap&amp; x){ DoubleWrap结果(this-&gt; value + x.value);