嵌套类的原始指针类成员无法返回分配的指向对象的数据

时间:2019-10-04 15:16:48

标签: c++ pointers

我有一个拥有者类GetCOREInterface()->GetActiveViewExp().GetViewCamera() 和一个H的类unique_ptr的实例(AH的所有者)。类A定义了一个嵌套类A,并且对B的实例具有unique_ptrBA的所有者)。反过来,B的{​​{1}}实例应该更新其A的各个方面,因此B拥有指向拥有它的A的原始指针。

我的问题是,当更新A的成员时,B无法准确返回它们。创建B并创建指向其拥有的A的指针时,其指针超出范围。

当不存在Holder类时(即A未被任何人拥有,但仍由其B实例指向),我可以使其工作。

考虑以下代码:

B

预期结果是:

A

但实际结果是:

#include <iostream>
#include <vector>
#include <memory>

// define class A
class A{



public:
  A(int x, int y);

  // define class B within A
  class B {
  public:
    B(A& a, int y);

  private:
    int b_y;
    A* b_a;

  public:
    void update_B(){
      std::cout << "Updating y of B belonging to A with x value " << b_a->a_x << std::endl;
      b_y += 1;
    }
  }; // end of class B

private:
  int a_x;
  std::unique_ptr<B> a_b;

public:
  void update_A(){
    std::cout << "Updating A...";
    a_x += 1;
    std::cout << " A's x is now " << a_x << std::endl;
    a_b->update_B();
  }
}; // end of class A


// define class H
class H{
public:
  H(int x, int y);
private:
  std::unique_ptr<A> h_a;

public:
  void update_h(){
    h_a->update_A();
  }
}; // end of class H

// define class A's constructor
A::A(int x, int y) {
  std::cout << "...creating instance of A... " << std::endl;
  a_x = x;
  a_b = std::make_unique<B> (B(*this, y)); // assign the unique ptr to B
  std::cout << "...A's x is set to " << x << std::endl;
}


// define class B's constructor
A::B::B(A& a, int y) {
  std::cout << ":- Creating instance of B within A..." << std::endl;
  b_a = &a; // assign B's pointer to the A instance that called it
  b_y = y;
  std::cout << ":- ...B's y is set to " << b_y << std::endl;
  std::cout << ":- ...B belongs to an A with value " << b_a->a_x << std::endl;
}


// define class H's constructor
H::H(int x, int y){
  std::cout << "Creating instance of H" << std::endl;
  h_a = std::make_unique<A> (A(x, y)); // assign the unique ptr to A
}


// main function
int main()
{
  // create instance of H
  H h(2, 10);
  // update the H function, which calls update_A and update_y
  h.update_h();
  return 0;
}

似乎B并未跟踪它最初指向的A实例。

我可以通过将Creating instance of H ...creating instance of A... :- Creating instance of B within A... :- ...B's y is set to 10 :- ...B belongs to an A with value 2 ...A's x is set to 2 Updating A... A's x is now 3 Updating y of B belonging to A with x value 3 显式传递给Creating instance of H ...creating instance of A... :- Creating instance of B within A... :- ...B's y is set to 10 :- ...B belongs to an A with value 2 ...A's x is set to 2 Updating A... A's x is now 3 Updating y of B belonging to A with x value <some massive number> 的{​​{1}}函数(如*this)来使代码正常工作,但我不明白上面的原因为何?工作。

非常感谢您提供的任何见识。

1 个答案:

答案 0 :(得分:1)

您被A的隐式move构造函数所困扰。问题是这一行:

h_a = std::make_unique<A> (A(x, y));

这会根据给定参数A构造指向A(x, y)的唯一指针。 IOW,您正在从A的一个已经构建的实例构造一个A。第二个实例是从第一个实例开始移动构造的,因此将接管第一个实例的B实例,该实例现在有一个指向其拥有实例的错误指针。

如果您修改代码以在对它们进行处理时打印AB的身份,则可以看到此信息:

Creating instance of H
...creating instance of A (0x7ffecd5a6d40)... 
:- Creating instance of B (0x7ffecd5a6cf0) within A (0x7ffecd5a6d40)...
:- ...B's y is set to 10
:- ...B belongs to an A with value 2
...A's x is set to 2
Updating A (0x19852a0)... A's x is now 3
Updating y of B (0x1985280) belonging to A (0x7ffecd5a6d40) with x value -849711776

如果我将您的代码更改为:

h_a = std::make_unique<A>(x, y);

...然后按预期工作:

Creating instance of H
...creating instance of A (0x877280)... 
:- Creating instance of B (0x7ffe479156c0) within A (0x877280)...
:- ...B's y is set to 10
:- ...B belongs to an A with value 2
...A's x is set to 2
Updating A (0x877280)... A's x is now 3
Updating y of B (0x8772a0) belonging to A (0x877280) with x value 3

但是,这不是完整的解决方案。您真正需要做的是为A提供一个move构造函数,以更新B的拥有实例以具有正确的指针,或者至少显式删除move构造函数,这样您就不会意外滥用课程。