【问题标题】:use back_inserter within C++ transform algorithm在 C++ 变换算法中使用 back_inserter
【发布时间】:2017-10-19 07:35:09
【问题描述】:
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;
                    });

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

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

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

【问题讨论】:

    标签: c++ algorithm stl transform


    【解决方案1】:

    当您分配给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,或者,您可以重复使用转换:

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

    【讨论】:

    • 你能帮我纠正一下吗?我真的很感激。
    • 谢谢你。我想指出 strtoupper 中的 toupper 需要更改为 ::toupper。
    【解决方案2】:

    @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 }
    

    【讨论】:

    • 如果d_firstinput 上的back_insert_iterator,这仍然可能会失败。 (它可能适用于您的情况,因为您通过值传递 input - 这本身不是一个好主意)
    • 我认为你是对的,我应该通过引用传递输入。我尝试并编译它。但我只是遇到了一个段错误。你能帮我吗?@chtz
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 2019-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-03-09
    相关资源
    最近更新 更多