0

从另一个问题我看到了这段代码:

template <typename T>
std::set<T> getUnion(const std::set<T>& a, const std::set<T>& b)
{
  std::set<T> result = a;
  result.insert(b.begin(), b.end());
  return result;
}

我们不能只使用下面的代码吗?:

template <typename T>
std::set<T> getUnion(std::set<T> a, const std::set<T>& b)
{
  a.insert(b.begin(), b.end());
  return a;
}

有什么区别吗??

我无法理解使用第一种方法的原因。

第二个代码是否禁止 RVO ?

4

2 回答 2

1

第一个版本采用std::set引用,这意味着您不会获得传递的参数的副本。复制实际上发生在 with 的初始化resulta。第二个按值获取参数,这意味着根据参数的值类别,编译器将调用复制/移动构造函数。特别是,如果参数是左值,则复制它,如果是右值,则移动它。

在第一个示例中,编译器很可能会丢弃 return 语句中的复制操作,这种优化称为返回值优化 (RVO)。第二个版本不能这样做,因为您没有返回局部变量。因此,您可以看到该函数的第二个版本必须产生至少一个额外的复制或移动操作,而第一个版本只处理一个。

于 2014-05-02T22:18:47.333 回答
1

实际上这两个功能是等价的。调用函数时,通过与参数 a 对应的参数的副本创建一个新集合

template <typename T>
std::set<T> getUnion(std::set<T> a, const std::set<T>& b)
{
//...

或者它是在函数体内创建的

template <typename T>
std::set<T> getUnion(const std::set<T>& a, const std::set<T>& b)
{
  std::set<T> result = a;
//...

然而,当函数被定义为第一种情况时,代码的读者会更清楚

template <typename T>
std::set<T> getUnion(const std::set<T>& a, const std::set<T>& b);

例如,函数可以声明为

template <typename T>
std::set<T> getUnion( const std::set<T> &a, std::set<T> b);

不能吗?

这些变化只会产生问题。

于 2014-05-02T22:22:32.127 回答