在this post中,其中一个答案建议以这种方式更改std::string
案例:
std::string str = "Hello World";
std::transform(str.begin(), str.end(),str.begin(), ::toupper);
我已经使用过它并且它在Visual Studio 2010中工作到目前为止。但是标准是否保证始终有效?我担心的是,我可以想象实现的可能性,其中写入输出迭代器(第三个参数)可能使输入迭代器(参数1和参数2)无效。
那么,总之,上述方法是否安全且便携?
答案 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要求:
op
和binary_op
不得使迭代器或子范围无效,或修改 范围[first1,last1]
,[first2,first2 + (last1 - first1)]
和[result,result + (last1 -first1)]
。[...]
5备注:如果是一元变换,
result
可能等于first
,或者first1
或者第一个2可能等于{{1}} 二进制变换。
答案 1 :(得分: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_first
和first1
指向同一个地方,但它们不是相同的迭代器!
在单个语句中递增这两个迭代器没有任何问题。
另一个实现是这样的(来自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)
是的,你可以使用输入迭代器作为输出迭代器,在修改算法上它只是意味着修改将在内联(在源容器上)而不是在其他目标容器上完成。