【发布时间】:2021-12-04 20:02:49
【问题描述】:
我试图避免使用emplace_back() 和reserve() 进行复制。但是当我尝试这样做时,我发现自己得到了 3 份副本,原因我无法真正理解。 reserve() 实际上有助于避免复制,但 emplace_back() 实际上对它没有任何作用(在这种情况下与 push_back() 的工作方式相同)。代码如下:
struct Vertex
{
size_t x, y, z;
Vertex(size_t x, size_t y, size_t z)
{
this->x = x;
this->y = y;
this->z = z;
}
Vertex(const Vertex& v)
: x(v.x), y(v.y), z(v.z)
{
std::cout << "\nCOPIED!\n";
}
};
int main()
{
std::vector<Vertex> vert;
vert.reserve(3);
vert.emplace_back(Vertex(1, 2, 3));
vert.emplace_back(Vertex(4, 5, 6));
vert.emplace_back(Vertex(7, 8, 9));
return 0;
}
输出是“复制!”的 3 倍。好吧,我尝试过这样的事情:
vert.emplace_back(std::move(Vertex(1, 2, 3)));
vert.emplace_back(std::move(Vertex(4, 5, 6)));
vert.emplace_back(std::move(Vertex(7, 8, 9)));
将我的对象转换为 r 值,但我又得到了 3 次“复制!”。
然后我尝试使用std::move 推送同一个对象 3 次,然后再次得到相同的结果:
Vertex vertex(1, 2, 3);
vert.emplace_back(vertex);
vert.emplace_back(vertex);
vert.emplace_back(vertex);
或
Vertex vertex(1, 2, 3);
vert.emplace_back(std::move(vertex));
vert.emplace_back(std::move(vertex));
vert.emplace_back(std::move(vertex));
我不明白我做错了什么。我使用 MSVS 2022 预览版 C++14。我也尝试在 C++14/17/20 上执行此操作,结果相同。有没有办法摆脱所有的副本?还是我理解错了?
【问题讨论】:
-
让它
vert.emplace_back(1, 2, 3);。emplace_back的全部意义在于,您可以将参数传递给对象的构造函数,向量可以使用该参数在适当的位置构造对象,而不是随后必须复制的对象实例。你使用它的方式,和push_back没有什么不同 -
你不能
std::move你的对象,因为它没有移动构造函数。 -
你使用
std::move,但是因为你有用户声明的复制构造函数,你阻止了编译器为你的类创建移动构造函数的可能性。您需要声明一个移动构造函数(例如使用Vertex(Vertex&&) = default;)。 -
即使有移动构造函数,也没有类成员变量的托管资源,所以没有什么可移动的。所以在这种情况下,移动与复制的作用相同。
标签: c++ vector move copy-constructor emplace