У меня есть этот код:
#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
вместо. В чем проблема?
Токенайзер не создает копию строки, которую вы передаете в качестве первого аргумента его конструктору, и при этом он не вычисляет все токены при построении, а затем кэширует их. Извлечение токена выполняется ленивым способом по запросу.
Однако, чтобы это было возможно, объект, для которого выполняется извлечение токена, должен оставаться в живых до тех пор, пока токен извлекается.
Здесь объект, из которого нужно извлечь токены, выходит из области видимости при инициализации tok2
заканчивается (то же самое относится к tok3
). Это означает, что вы получите неопределенное поведение когда объект токенизатора попытается использовать итераторы в эту строку.
Заметить, что tok3
дает вам ожидаемый результат чисто случайно. Ожидаемый результат действительно является одним из возможных выходов программы с неопределенным поведением.
Других решений пока нет …