将 std::list 公开为只读
我有一个类,其中包含 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
为什么不返回一个
const std::list&
呢?Why not return a
const std::list&
instead?无需公开列表本身(根本),只需将 const_iterator 公开到其开头和结尾即可。请参阅
cbegin()
和cend()
以获取执行此操作的帮助...Instead of exposing the list itself (at all) just expose
const_iterator
s to its beginning and end. Seecbegin()
andcend()
for help in doing this...返回 const 引用:
或者仅返回 const 迭代器:
Return a const reference:
or just return const iterators:
将数据成员暴露给外界存在依赖性问题。
如果您决定更改属性以获得更好的效果(因为
list
是最后的手段容器),或者因为您有新的需求,那么您的所有客户端都将受到影响,这很糟糕。一个简单的替代方案是提供
typedef
:如果您的客户使用您的别名,那么重新编译代码就很简单了。
另一种选择是创建您自己的迭代器类(不是那么困难),它将嵌入实际的迭代器。
您只需将所有操作转发到实际的迭代器,并且您的客户端(尽管如果您更改容器,它们将必须重新编译)不会意外地使用非别名类型。
然后,第三个解决方案与第一个解决方案类似,只是您抽象了类型...尽管(对于列表)效率相当低,所以我不会真正建议它:迭代器应该复制起来很便宜,但您不需要不想
新
任何东西。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
: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.
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.