std::move 一个即将被覆盖的变量
std::move a variable that is going to be overwritten
我 运行 上了一些 code
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
我有一个问题。为什么我们必须在 init
上使用 std::move,即使 init
是 int
?
我们不会 "have" 到 std::move
init
。我们(或者更确切地说,本例中的标准库)这样做是因为对于某些类型,移动比复制更有效。
even if init is int?
init
不一定是int
。它是T
,这是一个模板类型参数。
本身没有 "need,",在 T
是 int
的情况下使用 std::move
。但是,由于我们可以认为 std::move
基本上意味着 "please cast this expression to an rvalue,",所以在 T
是 int
的情况下,一个好的编译器在编译此代码时不应引入任何开销。因此,从这个意义上说,这段代码 肯定会 提高某些类型的性能 T
,并且 不太可能 损害某些类型的性能搬家是不行的。
你说得对,移动 int
与复制它没有什么不同。
这里,只有当 T
的重载 operator+
对左值和右值的行为不同时,std::move
才有用。
我从未听说过这样的 类,但我想它可能对以巧妙的方式重载 +
的动态数组很有用:
struct Vec
{
std::vector<int> elems;
};
// Returns a completely new vector.
Vec operator+(const Vec &a, const Vec &b)
{
assert(a.size() == b.size());
Vec ret(a.size());
for (std::size_t i = 0; i < a.size(); i++)
ret.elems[i] = a.elems[i] + b.elems[i];
return ret;
}
// Reuses storage of `a`.
Vec operator+(Vec &&a, const Vec &b)
{
assert(a.size() == b.size());
for (std::size_t i = 0; i < a.size(); i++)
a.elems[i] += b.elems[i];
return std::move(a);
}
// Reuses storage of `b`.
Vec operator+(const Vec &a, Vec &&b)
{
return std::move(b) + a;
}
// Reuses storage of `a`.
Vec operator+(Vec &&a, Vec &&b)
{
return std::move(a) + b;
}
编辑: 显然 std::string
做了类似的事情:如果可能,它的 +
重用其中一个操作数的存储。 (感谢@FrançoisAndrieux 和@Artyer。)
我 运行 上了一些 code
template<class InputIt, class T>
constexpr // since C++20
T accumulate(InputIt first, InputIt last, T init)
{
for (; first != last; ++first) {
init = std::move(init) + *first; // std::move since C++20
}
return init;
}
我有一个问题。为什么我们必须在 init
上使用 std::move,即使 init
是 int
?
我们不会 "have" 到 std::move
init
。我们(或者更确切地说,本例中的标准库)这样做是因为对于某些类型,移动比复制更有效。
even if init is int?
init
不一定是int
。它是T
,这是一个模板类型参数。
本身没有 "need,",在 T
是 int
的情况下使用 std::move
。但是,由于我们可以认为 std::move
基本上意味着 "please cast this expression to an rvalue,",所以在 T
是 int
的情况下,一个好的编译器在编译此代码时不应引入任何开销。因此,从这个意义上说,这段代码 肯定会 提高某些类型的性能 T
,并且 不太可能 损害某些类型的性能搬家是不行的。
你说得对,移动 int
与复制它没有什么不同。
这里,只有当 T
的重载 operator+
对左值和右值的行为不同时,std::move
才有用。
我从未听说过这样的 类,但我想它可能对以巧妙的方式重载 +
的动态数组很有用:
struct Vec
{
std::vector<int> elems;
};
// Returns a completely new vector.
Vec operator+(const Vec &a, const Vec &b)
{
assert(a.size() == b.size());
Vec ret(a.size());
for (std::size_t i = 0; i < a.size(); i++)
ret.elems[i] = a.elems[i] + b.elems[i];
return ret;
}
// Reuses storage of `a`.
Vec operator+(Vec &&a, const Vec &b)
{
assert(a.size() == b.size());
for (std::size_t i = 0; i < a.size(); i++)
a.elems[i] += b.elems[i];
return std::move(a);
}
// Reuses storage of `b`.
Vec operator+(const Vec &a, Vec &&b)
{
return std::move(b) + a;
}
// Reuses storage of `a`.
Vec operator+(Vec &&a, Vec &&b)
{
return std::move(a) + b;
}
编辑: 显然 std::string
做了类似的事情:如果可能,它的 +
重用其中一个操作数的存储。 (感谢@FrançoisAndrieux 和@Artyer。)