我有这段代码:
#include <boost/tokenizer.hpp>
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
int main() {
using namespace std;
boost::char_separator<char> sep(",");
string s1 = "hello, world";
tokenizer tok1(s1, sep);
for (auto& token : tok1) {
cout << token << " ";
}
cout << endl;
tokenizer tok2(string("hello, world"), sep);
for (auto& token : tok2) {
cout << token << " ";
}
cout << endl;
tokenizer tok3(string("hello, world, !!"), sep);
for (auto& token : tok3) {
cout << token << " ";
}
cout << endl;
return 0;
}
此代码产生以下结果:
hello world
hello
hello world !!
显然,第二行是错误的。我期待hello world
。问题是什么?
答案 0 :(得分:5)
标记生成器不会创建您传递的字符串的副本作为其构造函数的第一个参数,也不会在构造时计算所有标记然后缓存它们。令牌提取是在需要时以懒惰的方式执行的。
但是,为了使其成为可能,只要提取令牌,执行令牌提取的对象必须保持活动状态。
这里,当tok2
的初始化终止时(同样适用于tok3
),从中提取令牌的对象超出了范围。这意味着当tokenizer对象尝试将迭代器用于该字符串时,您将获得未定义的行为。
请注意,tok3
纯粹偶然为您提供了预期的输出。预期的输出确实是具有未定义行为的程序的可能输出之一。