【问题标题】:How can I use gsl::span and indicate ownership?如何使用 gsl::span 并指明所有权?
【发布时间】:2017-02-11 04:14:08
【问题描述】:

我想写一个函数:

  1. 将指针作为参数
  2. 以长度为参数
  3. 拥有指针指向的内存(例如,它可能会释放它,或者在某些数据结构中为其构造一个 unique_ptr 等)

现在,如果我想要 1+2,我会使用 gsl::span。如果想要 1+3,我会使用 owner<T*>。但是当我想要这三个时我该怎么办?我应该通过owner<gsl::span<T>> 吗?还有什么?

注意事项:

  • 您不能假设指针在堆中。
  • std::vector 要求太多。该函数不应要求调用者构造std::vector

【问题讨论】:

  • gsl::span 的意思是“不拥有所有权”。你想拥有所有权;因此,不要使用 gsl::span;如果您想拥有 [pointer + length] 数据集的所有权,请将它们存储到 [std::unique_ptr, length] 的元组中(并将该元组接收到您的函数中(尽管元组可能是坏主意 - 改为定义适当的类型)。
  • 拥有指针+长度几乎是std::vectorstd::experimental::dynarray...
  • @Ap31: 1. 没有人说指针在堆中。 2. 在这里,Vector 的语义太丰富了,不适合我的口味。 3. Dynarray 听起来很有趣,请考虑详细说明。
  • @utnapistim:我的印象是 gsl::span 只是意味着非拥有指针 + 长度。
  • 好吧,不管口味如何,在现代 C++ 中拥有一个动态大小的连续内存块,默认情况下使用 std::vector。任何其他解决方案都是有效的(我们仍在使用 C++ :)),但应该是合理的。 GSL 工具不是 C++ 标准库的替代品,而是允许在不进行风险重构的情况下处理遗留 API 和遗留实现的补充。考虑到这一点,我想澄清一下:您是否对您的 API 有任何特定要求(除了口味)会拒绝使用 std::vector

标签: c++ cpp-core-guidelines guideline-support-library


【解决方案1】:

一种选择是定义您自己的抽象基类来封装数据。比如:

template<typename T>
class DataHolder {
public:
  virtual ~DataHolder() = default;
  virtual gsl::span<T> get() const = 0;
};

那么你的函数可能看起来像:

void foo(std::unique_ptr<DataHolder<int>> data) {
  if (!data)
    return;
  for (auto v : data->get())
    std::cout << v << " ";
}

然后调用者可以使用他们想要的任何容器来实现基类。多态性的成本会很小,但不是基于每个元素。

如果您不想为多态性付费,也许您可​​以让您的函数接受模板参数。

template<typename DataHolder>
void foo(DataHolder data) {
  for (auto v : data())
    std::cout << v << " ";
}

DataHolder 的隐式接口可以通过以下方式满足:

struct VectorHolder {
    std::vector<int> data;
    gsl::span<const int> operator()() const { return data; }
};

或者如果您真的不想使用vector。你可以使用这样的东西(正如@utnapistim 所建议的那样):

struct ArrayHolder {
    std::unique_ptr<int[]> data;
    ptrdiff_t              length;
    gsl::span<const int> operator()() const { return {data.get(), length}; }
};

【讨论】:

  • 我不会定义特定于我自己代码的每个函数的抽象基类。另外,我不明白为什么我希望将 unique_ptr 双重间接指向一个跨度。
  • unique_ptr是管理span不能自己管理的数据的内存。
  • 您仍然有一个指向指针的指针,这在语义上是无偿的。恕我直言 - 我不喜欢这个解决方案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
相关资源
最近更新 更多