在传递给期望函数的引用时取消引用指针会创建一个副本,为什么?

时间:2018-01-24 15:06:20

标签: c++ copy-constructor dereference

考虑一个简单的例子

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时,这导致需要转换。

谢谢你们两位!

1 个答案:

答案 0 :(得分:1)

我认为副本是在std::make_pair()方法中进行的,该方法返回对由a->firsta->second *b复制的T和V类的两个实例组成的新对象的引用。否则,修改返回对中的任何内容也会修改fn()中引用传递的对象。

编辑:现在您已经提供了更多信息,我认为执行时会调用(* first).second的复制构造函数:a->second *b。由于我不知道你的操作员如何重载*,我想这意味着副本。