更喜欢过度指针的迭代器? [英] Prefer Iterators Over Pointers?
问题描述
这个问题是一个有评论的问题 here 但作为凹凸的一部分被删除。
This question is a bump of a question that had a comment here but was deleted as part of the bump.
对于那些看不到删除帖子的人,评论是我使用 const char *
而不是 string :: const_iterator 此答案中的code>:迭代器可能是一个更好的路径,因为它出现了这正是你的指针的处理方式。
For those of you who can't see deleted posts, the comment was on my use of const char*
s instead of string::const_iterator
s in this answer: "Iterators may have been a better path from the get go, since it appears that is exactly how your pointers seems be treated."
所以我的问题是这样,迭代器持有 string :: const_iterator
s在 const char *
上保留任何内在值,以便将我的答案转换为 string :: const_iterators
有意义吗?
So my question is this, do iterators hold string::const_iterator
s hold any intrinsic value over a const char*
s such that switching my answer over to string::const_iterators
makes sense?
推荐答案
简介
有ma使用迭代器而不是指针的好处是:
Introduction
There are many perks of using iterators instead of pointers, among them are:
- 发布中的不同代码路径 vs debug ,和;
- 更好的类型安全性,并且;
- 可以编写通用代码(迭代器可以是使用任何数据结构,如链接列表,而内在指针在这方面非常有限)。
- different code-path in release vs debug, and;
- better type-safety, and;
- making it possible to write generic code (iterators can be made to work with any data-structure, such as a linked-list, whereas intrinsic pointers are very limited in this regard).
除其他外,取消引用传递的迭代器范围的结尾是 undefined-behavior ,在这种情况下,实现可以自由地做任何必要的事情 - 包括提出诊断,说你做错了。
Since, among other things, dereferencing an iterator that is passed the end of a range is undefined-behavior, an implementation is free to do whatever it feels necessary in such case - including raising diagnostics saying that you are doing something wrong.
提供标准库实现, libstdc ++ ,通过 gcc 会在检测到故障时发出诊断信息(如果 调试模式 已启用。)
The standard library implementation, libstdc++, provided by gcc will issues diagnostics when it detects something fault (if Debug Mode is enabled).
示例
#define _GLIBCXX_DEBUG 1 /* enable debug mode */
#include <vector>
#include <iostream>
int
main (int argc, char *argv[])
{
std::vector<int> v1 {1,2,3};
for (auto it = v1.begin (); ; ++it)
std::cout << *it;
}
/usr/include/c++/4.9.2/debug/safe_iterator.h:261:error: attempt to
dereference a past-the-end iterator.
Objects involved in the operation:
iterator "this" @ 0x0x7fff828696e0 {
type = N11__gnu_debug14_Safe_iteratorIN9__gnu_cxx17__normal_iteratorIPiNSt9__cxx19986vectorIiSaIiEEEEENSt7__debug6vectorIiS6_EEEE (mutable iterator);
state = past-the-end;
references sequence with type `NSt7__debug6vectorIiSaIiEEE' @ 0x0x7fff82869710
}
123
如果我们使用指针,无论我们是否处于调试模式,都不会发生上述情况。
The above would not happen if we were working with pointers, no matter if we are in debug-mode or not.
如果我们不要为 libstdc ++ 启用调试模式,将使用性能更友好的版本(没有添加的簿记)实现 - 并且不会发布任何诊断信息。
If we don't enable debug mode for libstdc++, a more performance friendly version (without the added bookkeeping) implementation will be used - and no diagnostics will be issued.
由于迭代器的实际类型是实现定义的,这可用于提高类型安全性 - 但您必须检查实现的文档看看是否是这种情况。
Since the actual type of iterators are implementation-defined, this could be used to increase type-safety - but you will have to check the documentation of your implementation to see whether this is the case.
考虑下面的例子:
#include <vector>
struct A { };
struct B : A { };
// .-- oops
// v
void it_func (std::vector<B>::iterator beg, std::vector<A>::iterator end);
void ptr_func (B * beg, A * end);
// ^-- oops
int
main (int argc, char *argv[])
{
std::vector<B> v1;
it_func (v1.begin (), v1.end ()); // (A)
ptr_func (v1.data (), v1.data () + v1.size ()); // (B)
}
精化
- (A)取决于实现,可以是编译时间错误,因为
std :: vector< A> :: iterator
和std :: vector< B> :: iterator
可能不是同一类型。 - (B)总是编译,因为从
B隐式转换*
至A *
。
- (A) could, depending on the implementation, be a compile-time error since
std::vector<A>::iterator
andstd::vector<B>::iterator
potentially isn't of the same type. - (B) would, however, always compile since there's an implicit conversion from
B*
toA*
.
这篇关于更喜欢过度指针的迭代器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!