错误的标记化

r.v*_*r.v 2 c++ boost boost-tokenizer

我有这个代码:

#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;
}
Run Code Online (Sandbox Code Playgroud)

此代码生成以下结果:

hello  world 
hello  
hello  world  !!
Run Code Online (Sandbox Code Playgroud)

显然,第二行是错误的.我期待的是hello world.问题是什么?

And*_*owl 5

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

但是,为了使其成为可能,只要正在提取令牌,执行令牌提取的对象必须保持活动.

这里,当tok2终止的初始化(同样适用于tok3)时,从中提取令牌的对象超出范围.这意味着当tokenizer对象尝试将迭代器用于该字符串时,您将获得未定义的行为.

请注意,这tok3纯粹是偶然给出了预期的输出.预期的输出确实是具有未定义行为的程序的可能输出之一.

  • @rv:不,编译器没有弄清楚你的程序是否最终会提领无效的迭代器或悬空引用/指针 - 在一般情况下,这是不可能的 (2认同)