C++ 什么';通过C+有什么错+;引用迭代器?

C++ 什么';通过C+有什么错+;引用迭代器?,c++,pass-by-reference,iterator,C++,Pass By Reference,Iterator,我已经用这样的原型编写了一些函数: template <typename input_iterator> int parse_integer(input_iterator &begin, input_iterator end); //Comment: the return code is a pair of values, i.e. the parsed int and etc ... pair<int, input_iterator> parse(input_

我已经用这样的原型编写了一些函数:

template <typename input_iterator>
int parse_integer(input_iterator &begin, input_iterator end);
//Comment: the return code is a pair of values, i.e. the parsed int and etc ...
pair<int, input_iterator> parse(input_iterator start, input_iterator end)
{
}
这将使
i
设置为123,并将
p
指向
foo
之前的空格


后来有人告诉我(没有解释)通过引用传递迭代器是不好的形式。这是坏形式吗?如果是,原因是什么?

一般来说:

如果传递一个非
常量
引用,则调用方不知道迭代器是否正在修改

您可以传递一个
const
引用,但通常迭代器很小,与通过值传递相比没有任何优势

在您的情况下:


我认为您所做的没有任何错误,只是迭代器的使用不是太标准。

您的函数声明的第二个参数缺少引用,是吗

无论如何,回到你的问题:不,我从来没有读过任何东西说你不应该通过引用传递迭代器。引用的问题是,它们允许您更改引用的对象。在这种情况下,如果要更改迭代器,则可能会将整个序列弄糟,超出该点,从而导致无法进行进一步处理


只有一个建议:仔细键入参数。

我认为标准库算法只通过值传递迭代器(现在有人会对此发布一个明显的例外)-这可能是这个想法的起源。当然,没有人说您自己的代码必须看起来像标准库

当他们说“不要通过引用传递”时,可能是因为将迭代器作为值参数传递比通过常量引用传递更为正常/惯用:对于第二个参数,您是这样做的

然而,在本例中,您需要返回两个值:解析的int值和新的/修改的迭代器值;假设一个函数不能有两个返回码,将其中一个返回码编码为非常量引用是很正常的

另一种方法是将其编码如下:

template <typename input_iterator>
int parse_integer(input_iterator &begin, input_iterator end);
//Comment: the return code is a pair of values, i.e. the parsed int and etc ...
pair<int, input_iterator> parse(input_iterator start, input_iterator end)
{
}
//注释:返回代码是一对值,即解析后的int等。。。
对分析(输入迭代器开始,输入迭代器结束)
{
}

没有什么真正的错误,但它肯定会限制模板的使用。您不能只放置由其他对象返回或生成的迭代器,如
v.begin()
,因为这些迭代器是临时的。你总是首先要制作一份本地副本,这是一种不太好用的样板文件

一种方法是使其过载:

int parse_integer(input_iterator begin, input_iterator end, 
                  input_iterator &newbegin);

template<typename input_iterator>
int parse_integer(input_iterator begin, input_iterator end) {
    return parse_integer(begin, end, begin);
} 
int parse_integer(输入迭代器开始,输入迭代器结束,
输入(迭代器&newbegin);
模板
int parse_integer(输入迭代器开始,输入迭代器结束){
返回parse_整数(begin,end,begin);
} 
另一个选项是使用输出迭代器,其中数字将写入:

template<typename input_iterator, typename output_iterator>
input_iterator parse_integer(input_iterator begin, input_iterator end,
                             output_iterator out);
模板
输入迭代器解析整数(输入迭代器开始,输入迭代器结束,
输出(迭代器输出);
您将有返回值来返回新的输入迭代器。然后可以使用插入器迭代器将解析后的数字放入向量或指针中,直接放入整数或其数组中(如果您已经知道数字的数量)

int i;
b = parse_integer(b, end, &i);

std::vector<int> numbers;
b = parse_integer(b, end, std::back_inserter(numbers));
inti;
b=parse_整数(b,end,&i);
std::向量数;
b=解析_整数(b,end,std::back_插入器(数字));

在我看来,如果要这样做,参数应该是指向要更改的迭代器的指针。我不太喜欢非常量引用参数,因为它们隐藏了传递的参数可能会更改的事实。我知道有很多C++用户不同意我的观点,这很好。 然而,在这种情况下,迭代器被视为值参数非常常见,因此我认为通过非常量引用传递迭代器并修改传递的迭代器是一个特别糟糕的主意。这与迭代器通常使用的惯用方式背道而驰

既然有一种很好的方法可以做你想做的事情,而不存在这个问题,我认为你应该使用它:

template <typename input_iterator>
int parse_integer(input_iterator* begin, input_iterator end);
很明显,迭代器是可以更改的


顺便说一下,我还喜欢返回新的迭代器,并将解析后的值放入输出迭代器指定的位置

在这种情况下,我认为通过引用传递迭代器是完全明智的,只要它有良好的文档记录


值得注意的是,您的方法(通过引用传递迭代器以跟踪标记流时的位置)正是您所采用的方法。具体请参见的定义。总的来说,我发现boost::tokenizer设计得非常好,考虑得也很周全。

我也在考虑返回一对,但这需要一些应用程序代码的样板文件。。。除非您选择boost::tie。“您将无法只放置由其他对象返回或生成的迭代器(如v.begin()),因为这些迭代器将是临时的。”这就是C++0x右值引用的用途。:)我喜欢输出迭代器的想法,它非常适合stl ESQUE另一种选择(对于后期读者):返回::std::pair,类似于::std::map::insert。不,第二个参数是故意按值传递的,因为不需要按引用传递它。是,通过引用传递允许函数更改参数。这就是目的。我不明白你的意思。更改迭代器不能“破坏整个序列”。更改迭代器与更改范围内的数据不同。毕竟,这些都是常量迭代器。