繁体   English   中英

C ++容器,销毁后会自动删除元素

[英]C++ container which automatically deletes elements when destructed

我想在C ++中创建一个引用列表或引用映射,在引用销毁后会自动删除其元素。 这是一个演示想法的结构。

class Foo;

class Bar
{
    Foo foo;
};

void main(void)
{
    std::vector<Foo> foos;

    {
        Bar bar;
        foos.push_back(bar.foo);

        // foos[0] should be the same reference as bar.foo
    }

    // bar is now destructed
    // foos.size() should be 0
}

我的代码有两点错误。 当使用std :: vector调用push_back() ,它将创建Foo对象的副本。 这是不可接受的,因为foos的元素应该反映对bar.foo所做的任何更改。 其次,即使foos向量可以存储引用,将Foo对象保留在创建bar的作用域之后也不会从列表中删除。 理想情况下,我希望Foo引用在销毁后从foos删除。

在实施自己的解决方案之前,我很想知道提供此功能的任何第三方库(可能是Boost?),或者我应该使用的任何适当的技术或策略。 谢谢!

我认为最好的选择是使用弱指针容器。 (如果您的编译器由于某种原因不支持C ++ 11或TR1,则在Boost中可用。)

假设您已正确初始化对象,则弱指针将在破坏目标时自动使自身失效。

这是一些示例代码,用于在弱指针容器中获取所有有效指针。

template <class T>
std::vector<std::shared_ptr<T> > MassLock(const std::vector<std::weak_ptr<T> >& weakptrs)
{
    std::vector<std::shared_ptr<T> > sharedptrs;

    for(unsigned int i=0; i<weakptrs.size(); ++i)
    {
        if (std::shared_ptr<T> temp = weakptrs.at(i).lock())
        {
            sharedptrs.push_back(temp);
        }
    }

    return sharedptrs;
}

这是清除所有无效指针的方法。

template <class T>
struct isInvalid : public std::unary_function<T, bool>
{
    bool operator() (T rhs) { return !rhs.lock(); }
};

template <class T>
void EraseInvalid( std::vector<T>& targetlist )
{
    targetlist.erase( remove_if(targetlist.begin(), targetlist.end(), isInvalid<T>() ), targetlist.end());
}

如果需要多个对同一对象的引用,则可能需要一个容器,例如std::shared_ptr (如果没有C ++ 11,则来自Boost)。

通过使用weak_ptr(由Antimony建议)来更改列表以保留引用,并按如下所示自动删除被破坏的元素。

首先,让我们澄清一些措辞:标题应该是“ C ++容器,在销毁时会自动删除对元素的引用”,因为删除元素实际上会销毁它,因此您不希望在销毁时将其“删除”,而是希望从容器中删除对它的引用。

std::list<std::weak_ptr<Foo>> foos;

{
    // create a new entry in the container
    const auto& iter = foos.insert(foos.end(), std::weak_ptr<Foo>());
    // create an object of type "Foo" and store it in a shared_ptr
    std::shared_ptr<Foo> foo
        (new Foo
        // set a custom deleter that actually deletes the object
        // AND erases it from the container
        , [&foos, iter](Foo* ptr)
            {
                delete ptr;
                foos.erase(iter);
            }
        );
    // set the pointer to the element into the container
    *iter = foo;
}

// the shared_ptr "foo" ran out of scope;
// as there is no further strong reference to its object
// , the custom deleter was called which has removed the entry from the container
// so foos.size() is now 0

请注意,我将容器从矢量更改为列表,因为矢量可能会使迭代器无效(传递给自定义删除程序,请参见调整矢量的大小会使迭代器无效吗? ),而列表却没有。 如果要坚持使用向量,则可以使用索引作为传递给自定义删除器的元素的引用,但要注意,在end()之前在向量中插入元素会破坏该引用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM