Usages of std::move

Usages of std::move

本文关键字:move std of Usages      更新时间:2023-10-16

下面的问题是SO代码的简化版本。原始代码:

  • 接收不应修改或失效的结构
  • 创建一个不同的结构,其中包含从原始结构复制的一些数据
  • 新创建的结构是不可修改的,所有成员都const
  • 新创建的结构不能具有知道原始结构的构造函数

SO的简化代码没有原始结构,我只是用循环组成数据。然而,仍然重要的细节是新结构的构造函数将被传递std::vector。这些填充在循环中并移动到新结构中

我突然想到,新结构建成后就不需要std::vectorstd::move所以是合适的。我在下面的代码中将用法标记为"移动 1"、"移动 2"、"移动 3"和"移动 4":

#include <iostream>
#include <vector>
struct A {
const int m_a;
A() = delete;
A(const int a_a) : m_a(a_a) {}
void display() const { std::cout << "    " << m_a << "n"; }
};
struct B {
const std::vector<A> m_as;
const int            m_b;
B() = delete;
B(
std::vector<A>&& a_as,
const int        a_b
) :
m_as(std::move(a_as)), // Move 1
m_b(a_b)
{}
void display() const {
std::cout << "  " << m_b << ":n";
for (const A& a : m_as)
a.display();
}
};
struct C {
const std::vector<B> m_bs1;
const std::vector<B> m_bs2;
C() = delete;
C(
std::vector<B>&& a_bs1,
std::vector<B>&& a_bs2
) :
m_bs1(std::move(a_bs1)), // Move 2
m_bs2(std::move(a_bs2))  // Move 2
{}
void display() const {
std::cout << "0:n";
for (const B& b : m_bs1)
b.display();
std::cout << "1:n";
for (const B& b : m_bs2)
b.display();
}
};
int main() {
// Manually making up data, actual usage will take data from a different
// kind of structure and populate vectors
std::vector<B> bs1, bs2;
for (int i = 0; i < 3; ++i) {
std::vector<A> as;
for (int j = 0; j < 2; ++j)
as.emplace_back(j);
bs1.emplace_back(std::move(as), i); // Move 3
}
for (int i = 0; i < 3; ++i) {
std::vector<A> as;
for (int j = 0; j < 2; ++j)
as.emplace_back(j);
bs2.emplace_back(std::move(as), i); // Move 3
}
C c(std::move(bs1), std::move(bs2)); // Move 4
c.display();
return 0;
}

一些假设

我相信"移动
  • 1"和"移动2"之间没有显着区别
  • 我相信"招3"和"招4"之间没有显着区别
  • 据我所知,std::forward不是任何std::move用法的良好替代品,因为没有模板

问题:所有std::move用法是否有意义,或者其中任何一种都是不必要的?

你可以看到大多数std::move都是删除它们所必需的,你的代码将无法编译。唯一的例外是Move 1Move 2,代码仍然可以在没有它们的情况下编译,但只是因为调用了std::vector复制构造函数。

如果要从对象移动,则几乎总是需要使用std::move,唯一的例外是从临时移动和返回对象时。