将 std::list 公开为只读

发布于 2024-09-04 20:28:47 字数 165 浏览 8 评论 0原文

我有一个类,其中包含 std::list 等。我想公开这个列表,但只能以这样的方式公开:它包含的结构和数据是只读的,但仍然可以与迭代器一起使用。

我让它“工作”的方法是返回一份列表的副本。这使我的类“安全”,但当然无法阻止调用者修改其列表副本并且无法获取正确的数据。

有更好的办法吗?

I have a class that contains, among other things, an std::list. I want to expose this list but only in such a way that the structure and the data it contains are read only, but still can be used with iterators.

The way I've got it 'working' atm is to return a copy of the list. This leave my class 'safe' but of course does nothing to stop the caller from modifying their copy of the list and not getting the right data.

Is there a better way?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

坠似风落 2024-09-11 20:28:47

为什么不返回一个 const std::list& 呢?

Why not return a const std::list& instead?

清风夜微凉 2024-09-11 20:28:47

无需公开列表本身(根本),只需将 const_iterator 公开到其开头和结尾即可。请参阅 cbegin()cend() 以获取执行此操作的帮助...

Instead of exposing the list itself (at all) just expose const_iterators to its beginning and end. See cbegin() and cend() for help in doing this...

眼角的笑意。 2024-09-11 20:28:47

返回 const 引用:

const std::list<T>& getList() const;

或者仅返回 const 迭代器:

std::list<T>::const_iterator getListBegin() const;
std::list<T>::const_iterator getListEnd() const;

Return a const reference:

const std::list<T>& getList() const;

or just return const iterators:

std::list<T>::const_iterator getListBegin() const;
std::list<T>::const_iterator getListEnd() const;
心清如水 2024-09-11 20:28:47

将数据成员暴露给外界存在依赖性问题。

如果您决定更改属性以获得更好的效果(因为 list 是最后的手段容器),或者因为您有新的需求,那么您的所有客户端都将受到影响,这很糟糕。

一个简单的替代方案是提供 typedef

typedef std::list<Foo>::const_iterator const_iterator;

如果您的客户使用您的别名,那么重新编译代码就很简单了。

另一种选择是创建您自己的迭代器类(不是那么困难),它将嵌入实际的迭代器。

class const_iterator
{
public:

private:
  typedef std::list<Foo>::const_iterator base_type;
  base_type mBase;
};

您只需将所有操作转发到实际的迭代器,并且您的客户端(尽管如果您更改容器,它们将必须重新编译)不会意外地使用非别名类型。

然后,第三个解决方案与第一个解决方案类似,只是您抽象了类型...尽管(对于列表)效率相当低,所以我不会真正建议它:迭代器应该复制起来很便宜,但您不需要不想任何东西。

There is a dependency issue in exposing one's data member to the outside world.

If you decide to change your attribute for something better (because list are the last resort container), or because you have a new requirements, then all your clients will be impacted, and that is bad.

One simple alternative is to offer a typedef:

typedef std::list<Foo>::const_iterator const_iterator;

IF your clients use your alias, then it's a simple matter of recompiling the code.

Another alternative is to create your own iterator class (not that difficult) which will embed the actual iterator.

class const_iterator
{
public:

private:
  typedef std::list<Foo>::const_iterator base_type;
  base_type mBase;
};

You simply forward all the operations to the actual iterator, and your clients (though they will have to recompile if you change your container) cannot accidentally use an unaliased type.

Then, the 3rd solution is similar to the first, except that you abstract the type... it's quite inefficient though (for a list), so I would not really advise it: iterators are supposed to be cheap to copy, you don't want to new anything.

仄言 2024-09-11 20:28:47
class foo {
  private:
     typedef std::list<bar> bar_cont_t;

  public:
     typedef bar_const_t::const_iterator bar_const_iterator;

     bar_const_iterator bar_begin() const {return bar_data_.begin();}
     bar_const_iterator bar_end  () const {return bar_data_.end  ();}

     // whatever else

  private:
     bar_cont_t bar_data_;
};
class foo {
  private:
     typedef std::list<bar> bar_cont_t;

  public:
     typedef bar_const_t::const_iterator bar_const_iterator;

     bar_const_iterator bar_begin() const {return bar_data_.begin();}
     bar_const_iterator bar_end  () const {return bar_data_.end  ();}

     // whatever else

  private:
     bar_cont_t bar_data_;
};
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文