gpt4 book ai didi

c++ - 尝试包装 std 容器以存储右值引用(如 unique_ptr,但在堆栈上)

转载 作者:太空宇宙 更新时间:2023-11-04 11:54:03 28 4
gpt4 key购买 nike

我又在尝试做一些奇怪的事情了。

好的,这是总体思路。我想要一个 std::list (和 vector 等等)实际拥有它们包含的对象。我想将值移动到其中,并通过引用访问它们。

使用 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();

到现在为止?好的。现在,让我们使用堆栈语义和右值引用来完成它。我们不能只使用 list<T&&>出于显而易见的原因,所以我们必须创建一个新类:

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

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

当然,我可能想要一个 owningstackowningvector同样,理想情况下我们希望它被模板化:

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()end()函数应该返回一个与底层集合的迭代器一样工作的迭代器,除了 operator*()。通过 lvalue 引用而不是值返回项目。

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

当然,所有这些都是假设底层 std::list (或其他)可以被说服采用右值。如果push_back()将值复制为左值,那么这些都不起作用。从头开始编写容器代码会更好吗?如果我这样做了,有没有办法把 list 的大部分代码放在一起? , queue , stackvector合并到一个基类中,以节省几乎相同类的重写四次?

也许我可以引入一个中间类,某种包装器?所以owned<list<T>>可以继承自 list<refwrapper<T>>或者其他的东西?我知道 boost 有一个 reference_wrapper ,但我不确定它是否适合这种情况。

最佳答案

如果你想避免复制周围的元素,你可以使用 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"
...
}

关于c++ - 尝试包装 std 容器以存储右值引用(如 unique_ptr,但在堆栈上),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16922184/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com