【问题标题】:Erroneous tokenizing错误的标记化
【发布时间】:2013-06-09 16:42:24
【问题描述】:

我有这个代码:

#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。问题是什么?

【问题讨论】:

  • 我不确切知道标记器是如何工作的,但我希望这是一个范围问题。标记器可能只保留对字符串的引用,但字符串超出范围,因此在打印时是垃圾内存。

标签: c++ boost boost-tokenizer


【解决方案1】:

标记器不会创建您作为第一个参数传递给其构造函数的字符串的副本,也不会在构造时计算所有标记然后缓存它们。令牌提取是根据需要以惰性方式执行的。

但是,为了实现这一点,执行令牌提取的对象必须在提取令牌期间保持活动状态。

这里,当tok2 的初始化终止时,要从中提取标记的对象超出范围(同样适用于tok3)。这意味着当分词器对象尝试在该字符串中使用迭代器时,您将得到未定义的行为

请注意,tok3 为您提供预期的输出纯属偶然。预期的输出确实是具有未定义行为的程序的可能输出之一。

【讨论】:

  • 谢谢!那么编译器不应该抱怨我传递了一个右值吗?
  • @r.v:不,编译器不必确定您的程序最终是否会取消引用无效迭代器或悬空引用/指针 - 在一般情况下,这是不可能的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-20
  • 1970-01-01
  • 2010-10-29
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
相关资源
最近更新 更多