gpt4 book ai didi

c++ - std::reference_wrapper 在容器中的使用

转载 作者:可可西里 更新时间:2023-11-01 15:24:28 37 4
gpt4 key购买 nike

如果可以的话,我会从我的代码中删除所有原始指针 *,因为使用它们可能不是线程安全的,而且设计意图不明确(可选值、所有权等)。然而,有时候不使用指针并不是那么容易。例如,我们倾向于在多态类型的容器中使用指向基类型的指针:

class A : noncopyable { ... };
class B : public A { ... };

std::vector<A*> v;
v.emplace_back(new B);

// temporary container for some operation
std::vector<A*> selected;
if(check())
selected.emplace_back(v.front());

你对上面的代码有什么看法?谁是主人?它是共享所有权还是非共享所有权?这就是为什么我们应该为 v 这样做:

std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());

现在很明显 v 拥有对象,但我仍然不喜欢 selected 有一个原始指针,这使我的设计不直观。查看标准 C++ 库,我认为只有一种类型可以完成这项工作 - std::reference_wrapper :

std::vector<std::unique_ptr<A>> v;
v.emplace_back(make_unique<B>());

// temporary container for some operation
std::vector<std::reference_wrapper<A>> selected;
if(check())
selected.emplace_back(*v.front());

您如何看待该代码?这是一个好习惯吗?我知道 std::ref()std::cref 主要用于模板,但似乎在这里我们也可以使用它来清楚地说明我们的设计意图。我看到的唯一问题是我必须使用 get() 取消引用 std::reference_wrapper 并且没有 operator*()operator->() 内部具有与容器中相同的接口(interface),就像在带有 unique_ptr 的容器中一样。我应该自己写类似的东西吗?或者也许可以在未来的 C++ 版本中针对此类用例扩展 reference_wrapper?请分享您的反馈。

编辑:我更改了代码示例以更好地展示意图。

最佳答案

您已经提供了一个看起来不错的解决方案。我知道问题是“你感觉如何?”

我个人的感觉是,一方面需要在安全性和明确性与另一方面代码的简单性之间存在某种平衡。看起来您的解决方案可能过于努力地追求安全性并且过多地损害了简单性。每当我使用包含“弱引用”的容器时,我都使用原始指针来表示它们。确实,这可能会使对象的所有者是谁变得不太清楚,但它也有一些优点:您不必研究什么是“reference_wrapper”,并且代码清晰。如果你只是暂时使用它们(弱引用的容器)并且你封装了这种用法,那么所有权问题应该是最小的。

但我想这只是个人喜好的问题。让我建议为同一目的使用不同的类型。前提是您有能力使用 Boost。对于“强”引用(拥有资源),您可以使用 Steve Watanabe 的 Type Erasure图书馆。它不需要显式使用自由存储内存,我想对于小型类型它可以完全避免使用堆内存(使用小缓冲区优化)。它最近已被 Boost 接受,尽管我认为尚未发布。

对于弱引用,考虑使用 Boost.Optional 的“可选引用”:

int i = 0;
boost::optional<int&> oi = i; // note: int&
i = 2;
assert(*oi == 2);

它与 reference_wrapper 具有相同的语义。

关于c++ - std::reference_wrapper<T> 在容器中的使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13874673/

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