考虑一个简单的例子
template<class InputIterator,class InputIterator2, class OutputIterT, class Function, class T2>
OutputIterT foo(InputIterator first, InputIterator2 last, OutputIterT result, Function fn, const T2& x)
{
while (first!=last) {
*result=fn(*first,x);
++first;
}
return result;
}
传递的函数fn是
template<class T, class V>
T fn(const T& a, const V& b) {
return std::make_pair(a.first, a.second *b);
}
当我使用这段代码并检查被调用的构造函数时,我看到在每次调用fn(* first,x)时,都会调用复制构造函数。我发现这很难理解,因为函数参数是一个参考。请注意,正在使用的迭代器是map迭代器。为了避免不必要的复制,我改变了代码直接接受迭代器(fn函数),这样现在的行是
*result=fn(first,x);
,fn是
template<class Iter, class V>
T fn(Iter a, const V& b) {
return std::make_pair(a->first, a->second *b);
}
为什么要在第一种情况下创建副本,并调用fn?什么时候会发生?为什么会发生这种情况,即使函数参数是const引用?感谢您帮助我理解。
澄清,
的复制构造函数(*first).second
在进入函数fn之前,正在调用。
@IgorTandetnik在下面的评论中提供了正确的答案,@ SebastianRedl进一步理解了为什么会发生这种情况。
类型
的地图对象map<Key,Value>;
真的是
map<Key const,Value>;
即使程序员没有这样指定(如果省略const)。
现在,在实例化foo函数时,如果你(正如我所做的那样)将对类型提供为
pair<Key,Value>
这与地图中包含的对不匹配,即
pair<Key const, Value>
(再次,即使你没有明确说密钥应该是const)。当传递给函数fn时,这导致需要转换。
谢谢你们两位!
答案 0 :(得分:1)
我认为副本是在std::make_pair()
方法中进行的,该方法返回对由a->first
和a->second *b
复制的T和V类的两个实例组成的新对象的引用。否则,修改返回对中的任何内容也会修改fn()
中引用传递的对象。
编辑:现在您已经提供了更多信息,我认为执行时会调用(* first).second的复制构造函数:a->second *b
。由于我不知道你的操作员如何重载*,我想这意味着副本。