在C ++转换算法中使用back_inserter

时间:2017-05-19 08:51:25

标签: c++ algorithm stl transform

vector<string> v = {"AAAAidad", "bbbb", "ADWHIBQSDS", "Hi", "fes", "dafegrg", "QQEEQEQEQEQ
    E", "\"", "a"};
transform1(v.begin(), v.end(), back_inserter(v),
                     [] (string s) -> string{
                     for(char& c:s)
                     {
                          c = toupper(c);
                     }
                    return s;
                    });

使用上面的代码片段,我希望在v的末尾插入大写的字符串元素。 实际上,我只是得到以下输出

v = {"AAAAidad",    "bbbb", "ADWHIBQSDS",   "Hi",   "fes",  "dafegrg",  "QQEEQEQEQEQ",    "AAAAIDAD"}

只有第一个字符串被大写并插入。 向量中的其余字符串元素在哪里?

2 个答案:

答案 0 :(得分:5)

当您分配到back_insert_iterator时,它会在底层容器上调用push_back

在向量上调用push_back至少会使end迭代器失效,并可能使其他所有迭代器失效。

传递到transform的开始和结束迭代器可以在遍历期间的任何时候失效,此时整个事物都会显示未定义的行为。

这是一个没有UB的版本,并且不需要自定义转换功能:

const auto original_size = v.size();

// add original_size empty strings at the end
v.resize(original_size * 2);

// the first new empty string is also one-past-the end of the originals
auto first_empty = v.begin() + original_size;

transform(v.begin(), first_empty, first_empty, strtoupper);

其中strtoupper是您的原始lambda,或者,您可以重新使用transform:

std::string strtoupper(std::string s) {
    transform(s.begin(), s.end(), s.begin(), toupper);
    return s;
}

答案 1 :(得分:0)

@Useless也许你是对的,我使用自定义的transform1来解决它。而这次我没有使用缓存的结束迭代器。 谢谢!

 20 template<class Input,  class OutputIt, class UnaryOperation>
 21 OutputIt transform1(Input input, OutputIt d_first, UnaryOperation unary_op)
 22 {
 23     auto first1 = input.begin();
 24     while(first1 != input.end())                                                                                                      
 25     {
 26         *d_first++ = unary_op(*first1++);
 27     }
 28     return d_first;
 29 }