【问题标题】:Resource handle const correctness资源句柄 const 正确性
【发布时间】:2021-08-22 18:57:08
【问题描述】:

我有时无法理解 const 的正确性,尤其是当它是对象的逻辑 const 时。假设我有一个类是一些资源的句柄。如果它是一个 const 句柄,那么我不想允许通过它修改资源。它不拥有这个资源,它有点像它的“视图”。如果我复制它,我不会创建新资源。

template<typename T>
class Handle
{
private:
    T *res = nullptr; // just placeholder value...

public:
    //constructors and other code...

    const auto& getRes() const  {return *res;}
    auto& getRes()              {return *res;}

};

这里我有一个问题。如果我从这个 const 句柄制作非 const 副本,我可以修改资源。

void func(const Handle<int>& res)
{
    //res.getRes() = 10; // Error. good.
    auto res_copy = res;
    res_copy.getRes() = 10; // Not good.
}

我只是假设如果我将某些东西作为 const 传递给函数,那么我应该能够以某种方式强制执行这种逻辑常量。或者,也许我想错了。我知道标准库使用 const-iterator / iterator 或 string-view 之类的东西,它们总是 const 但不知道如何将其应用于这种情况。

我可以创建一个ConstHandle 或将Handle&lt;int&gt; 转换为Handle&lt;const int&gt;,但是我必须在函数中指定句柄的常量和资源的常量,例如:

void func(const Handle<const int>& res)

如果我只想将const auto&amp; handleconst HandleType 概念传递给函数,可能效果不佳。也许我想太多了,但我只是想在我的脑海中解决这个问题。

【问题讨论】:

  • 也许T *res 应该是const T *res。这是需要保持不变的资源,是吗?
  • 这就是为什么你同时拥有iteratorconst_iterator。您希望有两个模板,Handleconst_Handle,或其他具有适当继承的模板,并且您不能从 const_Handle 构造 Handle,但反之亦然。顺便说一句,这是shared_ptr 的设计缺陷。您必须拥有shared_ptr&lt;const T&gt; 而不是const_shared_ptr,它在将共享ptr 传递给可变对象到承诺不会修改它的函数时创建不必要的副本。

标签: c++ const-correctness


【解决方案1】:

我只是假设如果我将某些东西作为 const 传递给函数,那么我应该能够以某种方式强制执行这种逻辑 const。

这可能会导致令人惊讶的行为或无法执行的 constness。正如您所注意到的,您只需复制句柄即可获得可变句柄。

这与 const 指针不指向 const 数据的问题相同。

我建议您遵循标准对std::span 所做的事情。如果您希望数据为 const,则需要使用 std::span&lt;const int&gt;

在你的情况下,如果你想对该句柄指向的东西强制执行常量,那确实是 Handle&lt;const int&gt;


您也可以有一个ConstHandle,但由于您已经有一个模板参数来指定T,为了简单起见,我会使用它。为了便于使用,您也可以这样做:

template<typename T>
using ConstHandle = Handle<T const>;

【讨论】:

  • 我明白了!谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-26
  • 1970-01-01
  • 2014-05-03
  • 2020-03-29
  • 1970-01-01
相关资源
最近更新 更多