[英]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)
的副本。 但是,如果Node
和NodeIO
沒有正確實施的拷貝構造函數時, 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_ptr
的std::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構造函數期間,更新它包含的所有NodeIO
的owner
指針,並確保在調用Node
復制構造函數時正確構造了新的NodeIO
。 根據存儲NodeEditor
的方式,您可能應該對它們進行相同的操作。
檢查NodeEditor對象以及Node對象和NodeIo對象的壽命。 使用new運算符創建動態對象,或確保您對NodeEditor的實例化以及Node和NodeIo發生在同一范圍內。 檢查是否保留NodeEditor Object的Node容器的副本,並在釋放NodeEditor Object之后使用它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.