使用指向值的原始指针从 std::list<Value> 中擦除?

Posted

技术标签:

【中文标题】使用指向值的原始指针从 std::list<Value> 中擦除?【英文标题】:Erasing from std::list<Value> using a raw pointer to Value? 【发布时间】:2013-03-18 00:44:10 【问题描述】:

我有一个属于管理构造的std::list&lt;Value&gt;,每当调用工厂方法时都会分发Value * 指针。当需要销毁Value 时,这些指针会传回给管理器。但是,我不确定如何最好地使用这些指针来查找和擦除/删除元素。

class ValueManager
public:

    Value * createValue(ValueDef & def) 
        m_valueList.push_back( Value( def ) );
        return &m_valueList.back();
    

    void destroyValue(Value * target) 

        // Mystery!  
        // How does one remove/erase a list element
        // with only a pointer to it's value?

    

private:

    std::list<Value> m_valueList;

;

::erase::remove 似乎都不适合这项任务,一个采用迭代器而不是指针,而后者采用整个值,这是无法完成的,因为在这种情况下,没有可以接受==Values之间的比较方法,只有指针才能可靠的找到目标。

我的问题是,destroyValue() 可以采取的最有效的实现是什么?

【问题讨论】:

您返回的地址属于 iterator,而不是值。使用迭代器 itself 作为返回值(除了真正的std::list&lt;&gt; 之外,不要尝试此操作)。 @WhozCraig - 不确定我是否遵循,它返回存储为列表中最后一个元素的元素的地址,对吧?是的,我使用的是列表,因为它不会重新分配节点,从而使内存地址无效。 您应该返回一个std::list&lt;Value&gt;::iterator。在接收端使用它的语法与指针相同(*x 将使用迭代器的解引用运算符来获取底层值)。访问地址需要一点技巧(&amp;(*x)),但仍然可行。但是,现在您也可以将该迭代器用作包含 std::list&lt;Value&gt; 的基于迭代器的操作的直接输入,例如 erase() 等。 【参考方案1】:

简单:停止返回原始指针,并开始返回迭代器。然后想要销毁一个的用户将在它创建时收到的值传递,就像现在一样。并且取消引用仍然可以像使用原始指针一样工作。但是擦除也可以,而且效率很高。

【讨论】:

我想避免使用迭代器,因为它们在使用它的代码中需要冗长的 std::list&lt;Value&gt;::iterator 声明。此外,它还公开了迭代器访问未显式返回的其他元素的能力,例如使用++,如果使用的话,这将导致事情变得混乱。有没有办法只使用指针? 所以创建一个typedef,比如ValueIter。这样,只需再输入 2 个字符(与 Value * 相比)。如果您确实需要防止“移动”返回的迭代器,只需创建自己的类类型并返回它,并让它包含一个迭代器并实现 operator* 以支持取消引用。

以上是关于使用指向值的原始指针从 std::list<Value> 中擦除?的主要内容,如果未能解决你的问题,请参考以下文章

指向std :: vector和std :: list元素的指针

指向 std::vector 和 std::list 元素的指针

使用 std::initializer_list 创建指向 std::min 的函数指针

如何从 STL 列表中的迭代器访问指向结构的指针而不是其元素

std::initializer_list 返回值的生命周期

Go笔记-指针