C ++按值返回-内部的指针会发生什么? [英] C++ return by value - what happens with the pointer inside?

查看:73
本文介绍了C ++按值返回-内部的指针会发生什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

因此,我遇到了一些SegFaults,并且想知道是否有人可以更深入地向我解释这是如何工作的.

So I'm having a bit of SegFaults and was wondering if someone can explain me in higher depth how does this work.

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

I have a wrapper class around a numeric variable, and I'm trying to build a compute tree of the expression. Here is a sample code:

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

The problem I got is for an expression like x = a+b+c+d; When I try to look for the parents of x, it has 2 parents, but parents[0].parents[0] is nil, e.g. for some reason the pointer to the allocated place does not work or the allocated memory is destroyed?

如果有人可以给我建议解决方法,为什么会发生这种情况,我很感兴趣.

I'm quite interested if anyone can advise me on a workaround and why this happens.

在此代码上举一个例子:

To give an example on this code:

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]-()

但是我得到的结果(通常在不同的运行中会有所不同):

But the result I get (usually different on different runs):

[10]-(9,0x7ffffd5e2f00,4,0x7ffffd5e2de0,)
[9]-(33,0x1c6da10,3,0x7ffffd5e2db0,)
Process finished with exit code 139

我的猜测是,运算符的返回实际上复制了DoubleWrap变量,因此父级中的指针指向的值超出范围并释放了内存?

My guess is that the return of the operator in fact copies the DoubleWrap variable, thus value to which the pointer in parents is pointing to goes out of scope and the memory is released?

临时解决方案是通过引用返回,但是问题是为什么并且有一个合适的解决方案?

The temporary solution was to return by reference, but the question is why and is there a proper one?

PS:修复了我之前遇到的一个错误,该错误是setParents中的一个错误.

PS: Fixed a previous mistake I got which is a mistake in setParents.

推荐答案

您的问题是,您正在将指向临时对象的指针添加到向量中.

Your problem is that you're adding pointers to temporary objects to the vector.

DoubleWrap a = dw + dw2 + dw3;

以上将首先调用dw.operator+(dw2).这将创建一个临时对象,我们将其命名为temp.然后,它调用temp.operator+(dw3).现在在operator+内部,是对setParents的调用,您可以在其中将temp作为parent传递.然后,您获取temp的地址(至少这是代码为了进行编译而应该执行的操作)并将其添加到child的向量中.

The above will first call dw.operator+(dw2). That creates a temporary object, let's name it temp. It then calls temp.operator+(dw3). Now inside operator+ there's this call to setParents where you pass temp as the parent. You then take the address of temp (at least that's what the code should be doing in order to compile) and add it to the vector of child.

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

Now when the call to operator+ returns, temp gets destroyed, and the vector in a contains a pointer to a non-existing object.

您可以通过使用shared_ptr将元素存储在向量中来解决此问题.请注意,如果可以使用参照循环,则应小心使用weak_ptr中断那些循环(以下代码中未包含该循环的实现).最终代码如下所示:

You could solve this by storing the elements in the vector using shared_ptr. Note that if referential cycles are possible you should be careful to break those cycles with weak_ptr (I didn't include an implementation for that in the below code). Here's what the final code could look like:

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 ++按值返回-内部的指针会发生什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆