将引用转换为共享指针

convert Reference to shared pointer

我有一个类似

的功能
void Element::setNodes(const BaseClass& input0, const BaseClass& input1)

这是通过传递派生的 class 来调用的。

setInputNodes(DerivedClass1, DerivedClass2)

我遇到的麻烦是我想将节点存储在向量中。我有这个

std::vector<std::shared_ptr<BaseClass>> m_inputNode;

函数为

void Element::setNodes(const BaseClass& input0, const BaseClass& input1)
{
m_inputNode.push_back(input0);
m_inputNode.push_back(input1);
}

这不起作用,我必须将它存储为指针,否则我会遇到对象切片。我需要更改 API 并传递指针吗?我想尽量少改。

如果您知道其他人正在管理矢量元素的生命周期,则使用 std::vector<const BaseClass*> 作为类型,并使用 &input0 等。将元素推入向量时。

这里很难使用 std::shared_ptr 指针,因为在使用时,您不知道对象是如何创建的。

如果您想保留您的参考资料,那么您可以随时将它们包含在 std::reference_wrapper 中;将 std::vector<std::reference_wrapper<const BaseClass>> 设置为类型。但所有权问题仍然普遍存在;你最终可能会得到一个悬挂引用的向量。

既然你说了,

I want a pointer/reference to the original.

唯一的选择是删除 shared_ptr 并使用非拥有指针:

std::vector<BaseClass const*> m_inputNode;

void Element::setNodes(BaseClass const& input0, BaseClass const& input1) {
    m_inputNode.push_back(&input0);
    m_inputNode.push_back(&input1);
}

(如果您需要非const 指针,请删除所有const。)

shared_ptr从根本上表达了所有权,这似乎不是你所追求的。

但是如果我误解了你,而你实际上想将对象的(共享)所有权授予你的向量,你还需要通过共享指针将对象传递到你的函数中:

void Element::setNodes(std::shared_ptr<BaseClass> input0, std::shared_ptr<BaseClass> input1) {
    m_inputNode.push_back(input0);
    m_inputNode.push_back(input1);
}

您必须将指针指向您的元素:

void Element::setNodes(const BaseClass& input0, const BaseClass& input1)
{
    m_inputNode.push_back(&input0);
    m_inputNode.push_back(&input1);
}

因此 shared_ptr<> 必须指向 const BaseClass。如果您不希望这样,则必须从参数规范中删除 const

我不推荐这样的 API 来满足您的需求。您没有为调用者明确表示您记住了指向对象的指针。当您稍后尝试使用它们时,他可能会传入堆栈分配对象甚至临时对象,这些对象不再有效:

myElement.setNodes(createElement0(), createElement1());

更愿意明确说明您的功能的用户必须期待什么。

void Element::setNodes(std::shared_ptr<BaseClass> input0,
                       std::shared_ptr<BaseClass> input1)
{
    m_inputNode.push_back(input0);
    m_inputNode.push_back(input1);
}

现在用户必须明确提供指针:

myElement.setNodes(std::make_shared<Element>(createElement0()),
                   std::make_shared<Element>(createElement1()));

这告诉用户,您将获得该对象的共享所有权。