1

我正在尝试再次做一些奇怪的事情。

好的,这是一般的想法。我想要一个std::listvector等等)实际上拥有它们包含的对象。我想值移入其中,并通过引用访问它们。

使用 unique_ptr 列表的示例:

using namespace std;
list<unique_ptr<T>> items;     // T is whatever type
items.push_back(make_unique(...));
items.push_back(make_unique(...));

for ( unique_ptr<T> item : items )
    item.dosomething();

跟我到现在?好的。现在,让我们用堆栈语义和右值引用来做这件事。由于显而易见的原因,我们不能只使用 a list<T&&>,所以我们必须创建一个新类:

using namespace std;
owninglist<T> items;
items.push_back(T());
items.push_back(T());

for ( T& item : items )
    item.dosomething();

当然,我可能也想要一个owningstackor owningvector,所以理想情况下我们希望它被模板化:

owning<std::list<T>> items;

该类owning<U<T>>应该继承基础集合具有的任何push_back()pop_front()功能。大概要实现这一点,我需要编写一个通用基类,并为具有不寻常功能的集合派生明确的特化:

template<typename T> owning<std::queue<T>> : owningbase<T> {
    void push_front() { ... }
}

我被困在迭代器上。begin()and函数应该返回一个迭代器,其end()工作方式与基础集合的迭代器相同,除了通过左值引用而不是按值operator*()返回项目。

我们需要某种方法将项目的所有权再次从列表中转移出去。也许迭代器可以有一个operator~将项目作为右值返回,从列表中删除项目并使迭代器无效?

当然,所有这一切都是假设std::list可以说服底层(或其他任何东西)采用右值。如果push_back()将值复制为左值,那么这一切都不起作用。从头开始编写容器会更好吗?list如果我这样做了,是否有某种方法可以将、和的大部分代码放入单个基类中queue,以节省将几乎相同的类重写四次?stackvector

也许我可以引入一个中间类,某种包装器?那么owned<list<T>>可以继承list<refwrapper<T>>还是什么?我知道 boost 有一个reference_wrapper,但我不确定它是否适合这种情况。

4

1 回答 1

1

如果你想避免复制元素,可以使用 std::move。

因此,如果您有一个 std::list ,您可以通过将它们移入来填充它:

SomeBigObject sbo;

std::list<SomeBigObject> list;
list.push_back(SomeBigObject()); // SomeBigObject() is a rvalue and so it is moved
list.push_back(std::move(sbo));  // sbo may not be a rvalue so you have to move it

// For construction you can also use std::list::emplace
list.emplace(list.end());        // construct the value directly at the end of the list

要访问它们,您可以简单地使用基于范围的循环:

for(auto& i :list)
    ...

如果要将它们移出容器,也可以使用 std::move。对象被移出容器,但残留物仍将在容器中,因此您必须擦除它们:

for(auto it = list.begin; it != lsit.end();)
{
    // the value of *it is moved into obj;
    // an empty value of "SomeBigObject" will remain so erase it from the list
    SomeBigObject obj = std::move(*it);

    it = list.erase(it);

    // do something with "obj"
    ...
}
于 2013-06-04T16:16:19.133 回答