gpt4 book ai didi

C++ 按值返回 - 里面的指针会发生什么?

转载 作者:行者123 更新时间:2023-11-28 06:21:50 25 4
gpt4 key购买 nike

所以我遇到了一些段错误,想知道是否有人可以更深入地向我解释这是如何工作的。

我有一个围绕数字变量的包装器类,我正在尝试构建表达式的计算树。这是一个示例代码:

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 的 parent 时,它有 2 个 parent ,但 parents[0].parents[0] 为 nil,例如由于某种原因,指向分配位置的指针不起作用或分配的内存被破坏?

如果有人可以就解决方法以及为什么会发生这种情况向我提供建议,我将非常感兴趣。

举个例子:

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 变量,因此 parents 中的指针指向的值超出范围并释放内存?

临时解决方案是通过引用返回,但问题是为什么以及是否有合适的方法?

PS: 修正了我之前的一个错误,是 setParents 的错误。

最佳答案

您的问题是您要将指向临时对象 的指针添加到 vector 中。

DoubleWrap a = dw + dw2 + dw3;

上面会先调用dw.operator+(dw2)。这会创建一个临时对象,我们将其命名为 temp。然后调用 temp.operator+(dw3)。现在在 operator+ 中有对 setParents 的调用,您将 temp 作为 parent 传递。然后获取 temp 的地址(至少这是代码为了编译应该做的)并将其添加到 child 的 vector 中。

现在,当对 operator+ 的调用返回时,temp 被销毁,并且 a 中的 vector 包含一个指向不存在对象的指针.


您可以通过使用 shared_ptr 将元素存储在 vector 中来解决这个问题。请注意,如果引用循环是可能的,您应该小心地使用 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;

关于C++ 按值返回 - 里面的指针会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29189033/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com