9

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

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

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

那么,综上所述,上述方法安全便携吗?

4

3 回答 3

11

Yes, this is guaranteed to be safe (as long as operation itself doesn't modify the elements or invalidate iterators).
From chapter [alg.transform] from draft n3337:

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 Requires: op and binary_op shall not invalidate iterators or subranges, or modify elements in the ranges [first1,last1], [first2,first2 + (last1 - first1)], and [result,result + (last1 -first1)].

[...]

5 Remarks: result may be equal to first in case of unary transform, or to first1 or first2 in case of binary transform.

于 2013-10-05T17:43:41.240 回答
3

如果您研究第一个可能的实现std::transform

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编辑

于 2013-10-05T17:40:06.467 回答
2

Yes, you can use the input iterator as the output iterator also, on a modifying algorithm it just means the modification will be done inline (on the source container) rather than on some other destination container.

于 2013-10-05T17:44:20.803 回答