簡體   English   中英

c ++從構造函數傳遞指針到構造函數

[英]c++ passing pointer from constructor to constructor

我正在學習C ++,並且創建了3個類:NodeEditor,Node,NodeIO。

本質上,編輯器包含一個節點向量,每個節點都有一個NodeIO實例向量。

我希望每個類都可以在其中引用“所有者”。

基本上,NodeIO構造函數從其in節點獲取一個指針,而Node則向其in編輯器獲取一個指針。

class NodeEditor {
    NodeEditor() {
        ...push_back(Node(this));
    }
}

class Node {
    NodeEditor* owner;
    Node(NodeEditor* _owner) : owner{ _owner } {
        ...push_back(NodeIO(this));
    }
}

class NodeIO {
    Node* owner;
    NodeIO(Node* _owner) : owner{ _owner } { }
}

然后,我稍后需要使用_owner指針。

當我在項目中嘗試此操作時,起初_owner指針指向正確的位置,但是一旦以后需要檢索它,實際的對象將不再存在於該指針位置。

我有什么選擇可以使這種布局起作用? 在這種情況下,還有沒有其他推薦的模式可以遵循。

您尚未顯示任何副本構造函數。 到此為止,我假設您依賴於編譯器提供的默認副本構造函數。 那就是問題的根源。

使用時:

    ...push_back(Node(this));

NodeEditor ,您正在存儲Node(this)的副本。 但是,如果NodeNodeIO沒有正確實施的拷貝構造函數時, NodeIO對象在Node中的對象std::vector將指向一個Node對象,它是無效的-臨時Node對象。


這是顯示問題的示例程序。

#include <iostream>
#include <vector>

struct Node;

struct NodeIO {
   Node* owner;
   NodeIO(Node* _owner) : owner{ _owner } { }
};

struct NodeEditor;

struct Node {
   NodeEditor* owner;
   Node(NodeEditor* _owner) : owner(_owner)
   {
      std::cout << (void*)this << std::endl;
      nodeIOList.push_back(NodeIO(this));
      nodeIOList.push_back(NodeIO(this));
   }

   std::vector<NodeIO> nodeIOList;
};

struct NodeEditor {
   NodeEditor()
   {
      nodeList.push_back(Node(this));
      nodeList.push_back(Node(this));
   }
   std::vector<Node> nodeList;
};

int main()
{
   NodeEditor editor;
   for ( auto& node : editor.nodeList )
   {
      std::cout << (void*)(&node) << std::endl;
      for (auto& nodeIO : node.nodeIOList )
      {
         std::cout << (void*)(nodeIO.owner) << std::endl;
      }
   }
}

輸出:

0x7ffe53d34c30
0x7ffe53d34c50
0xae10c0
0x7ffe1af7a2a0
0x7ffe1af7a2a0
0xae10e0
0x7ffe1af7a2c0
0x7ffe1af7a2c0

輸出清楚地顯示了指針的值Node使用構建的對象Node(this)和指針的值提供給Node是在商店對象std::vector<Node> 請注意, NodeIO對象仍指向臨時Node對象。 他們在main中懸掛指針。


我嘗試了快速修復,但是沒有用。 我需要做更多的工作。


這是可與默認副本構造函數一起使用的解決方案。 它使用std::vector std::shared_ptrstd::vector而不是對象的std::vector

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

struct Node;

struct NodeIO {
   Node* owner;
   NodeIO(Node* _owner) : owner{ _owner } { }
};

struct NodeEditor;

struct Node {
   NodeEditor* owner;
   Node(NodeEditor* _owner) : owner(_owner)
   {
      std::cout << (void*)this << std::endl;
      nodeIOList.push_back(std::make_shared<NodeIO>(this));
      nodeIOList.push_back(std::make_shared<NodeIO>(this));
   }

   std::vector<std::shared_ptr<NodeIO>> nodeIOList;
};

struct NodeEditor {
   NodeEditor()
   {
      nodeList.push_back(std::make_shared<Node>(this));
      nodeList.push_back(std::make_shared<Node>(this));
   }
   std::vector<std::shared_ptr<Node>> nodeList;
};

int main()
{
   NodeEditor editor;
   for ( auto& node : editor.nodeList )
   {
      std::cout << (void*)(node.get()) << std::endl;
      for (auto& nodeIO : node->nodeIOList )
      {
         std::cout << (void*)(nodeIO.get()->owner) << std::endl;
      }
   }
}

輸出:

0x1460c30
0x1461110
0x1460c30
0x1460c30
0x1460c30
0x1461110
0x1461110
0x1461110

將事物添加到向量中時,向量中的所有元素都可能移動。 因此,在添加Node ,所有現有NodeIO的所有者指針都可能無效。

要解決此問題,您需要

  • 使用其他數據結構並禁用Node的復制和移動構造函數,或者
  • Node的move構造函數期間,更新它包含的所有NodeIOowner指針,並確保在調用Node復制構造函數時正確構造了新的NodeIO

根據存儲NodeEditor的方式,您可能應該對它們進行相同的操作。

檢查NodeEditor對象以及Node對象和NodeIo對象的壽命。 使用new運算符創建動態對象,或確保您對NodeEditor的實例化以及Node和NodeIo發生在同一范圍內。 檢查是否保留NodeEditor Object的Node容器的副本,並在釋放NodeEditor Object之后使用它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM