输入迭代器和std :: transform中的输出迭代器来自同一个容器是否安全?

时间:2013-10-05 17:19:25

标签: c++ stl

this post中,其中一个答案建议以这种方式更改std::string案例:

std::string str = "Hello World";
std::transform(str.begin(), str.end(),str.begin(), ::toupper);

我已经使用过它并且它在Visual Studio 2010中工作到目前为止。但是标准是否保证始终有效?我担心的是,我可以想象实现的可能性,其中写入输出迭代器(第三个参数)可能使输入迭代器(参数1和参数2)无效。

那么,总之,上述方法是否安全且便携?

3 个答案:

答案 0 :(得分:9)

是的,这保证是安全的(只要操作本身不修改元素或使迭代器无效)。
来自草案n3337的第[alg.transform]章:

template<class InputIterator, class OutputIterator,  
    class UnaryOperation>  
OutputIterator  
transform(InputIterator first, InputIterator last,  
    OutputIterator result, UnaryOperation op);  

template<class InputIterator1, class InputIterator2,  
    class OutputIterator, class BinaryOperation>  
OutputIterator  
transform(InputIterator1 first1, InputIterator1 last1,  
    InputIterator2 first2, OutputIterator result,  
    BinaryOperation binary_op);  
  

2要求:opbinary_op不得使迭代器或子范围无效,或修改   范围[first1,last1][first2,first2 + (last1 - first1)][result,result + (last1 -first1)]

     

[...]

     

5备注:如果是一元变换,result可能等于first,或者first1或者第一个2可能等于{{1}}   二进制变换。

答案 1 :(得分:3)

如果您查看std::transform

first possible implementation
template<class InputIt, class OutputIt, class UnaryOperation>
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, 
                   UnaryOperation unary_op)
{
    while (first1 != last1) {
        *d_first++ = unary_op(*first1++);
    }
    return d_first;
}

可能看起来它并非“安全”。

然而,std::transform(str.begin(), str.end(),str.begin(), ::toupper);

d_firstfirst1指向同一个地方,但它们不是相同的迭代器!

在单个语句中递增这两个迭代器没有任何问题。

另一个实现是这样的(来自MingW头文件),等效,但看起来更清洁

template<class InputIt, class OutputIt, class UnaryOperation>
OutputIt transform(InputIt first1, InputIt last1, OutputIt d_first, 
                   UnaryOperation unary_op)
{

  for (; first1 != last1; ++first1, ++d_first)
    *d_first = unary_op(*first1);

    return d_first;
}

已编辑感谢John Bartholomew

答案 2 :(得分:2)

是的,你可以使用输入迭代器作为输出迭代器,在修改算法上它只是意味着修改将在内联(在源容器上)而不是在其他目标容器上完成。