1

下面是一个反模式:

auto f() {
  std::vector<int> v(100000);
  return std::move(v); // no need to use std::move thanks to RVO (return value optimization)
}

使用 astd::move甚至会产生最差的代码(见这里

但是,在以下情况下我应该怎么做:

auto f() {
  std::vector<int> v0(100000);
  std::vector<int> v1(100000);
  return std::make_pair(std::move(v0),std::move(v1)); // is the move needed?
}
4

2 回答 2

1

对于第二个片段,

auto f() {
  std::vector<int> v0(100000);
  std::vector<int> v1(100000);
  return std::make_pair(std::move(v0),std::move(v1)); // is the move needed?
}

return返回std::make_pair()函数的结果。那是一个 RValue。

但是,OP 的问题可能浓缩为是否(或为什么不)命名返回值优化仍然适用于v0/v1当返回为std::pair.

因此,忽略了v0/不再v1是主题return,而是成为std::make_pair(). 因此,v0/v1是 LValues -std::move(v0), std::move(v1)如果打算进行移动语义,则必须应用它们将它们变成 RValues。


关于大肠杆菌的演示

#include <iostream>

template <typename T>
struct Vector {
  Vector(size_t n)
  {
    std::cout << "Vector::Vector(" << n << ")\n";
  }
  Vector(const Vector&)
  {
    std::cout << "Vector::Vector(const Vector&)\n";
  }
  Vector(const Vector&&)
  {
    std::cout << "Vector::Vector(const Vector&&)\n";
  }
  
};

auto f1() {
  Vector<int> v(100000);
  return std::move(v); // over-pessimistic
}

auto f2() {
  Vector<int> v(100000);
  return v; // allows NRVO
}

auto f3() {
  Vector<int> v0(100000);
  Vector<int> v1(100000);
  return std::make_pair(v0, v1); // copy constructor called for v0, v1
}    

auto f4() {
  Vector<int> v0(100000);
  Vector<int> v1(100000);
  return std::make_pair(std::move(v0),std::move(v1)); // move constructor called for v0, v1
}

#define DEBUG(...) std::cout << #__VA_ARGS__ << ";\n"; __VA_ARGS__ 

int main()
{
  DEBUG(f1());
  DEBUG(f2());
  DEBUG(f3());
  DEBUG(f4());
}

输出:

f1();
Vector::Vector(100000)
Vector::Vector(const Vector&&)
f2();
Vector::Vector(100000)
f3();
Vector::Vector(100000)
Vector::Vector(100000)
Vector::Vector(const Vector&)
Vector::Vector(const Vector&)
f4();
Vector::Vector(100000)
Vector::Vector(100000)
Vector::Vector(const Vector&&)
Vector::Vector(const Vector&&)
于 2022-02-23T18:11:47.147 回答
1

是的,在后一种情况下需要移动以避免复制。

但是,这会更好:

return std::make_pair(
    std::vector<int>(100000),
    std::vector<int>(100000));
于 2022-02-23T18:15:03.947 回答