考虑到C++编译器在实例化临时对象和调用返回值优化等机制方面的灵活性,通过查看一些代码并不总是清楚是否会调用移动或复制语义(或者调用多少)。
几乎感觉这些原语是为附带优化而存在的。也就是说,你可能会得到它们,也可能得不到。当很难控制moves本身的调用时,似乎很难设计任何一种利用moves的资源管理策略。
有没有一种方法可以清楚地(简单地)预测在某些代码中可能发生的复制和移动的位置和数量?理想情况下,不需要是编译器内部的专家就能做到这一点。
发布于 2018-08-24 15:17:10
似乎很难设计任何一种利用移动的资源管理策略,因为很难控制移动本身的调用。
我要反驳这一点。在设计资源处理类时,利用移动语义应该独立于客户端代码中如何或何时发生复制或移动构造。一旦有了move-ctor/assignment,就可以设计客户端代码来利用这些特殊成员函数的存在。
有没有一种方法可以清楚地(简单地)预测某些代码中可能发生的复制和移动的位置和数量?
很难简单地说出这里的意思,但我是这样理解的:
struct A{};A func() { return A {};}
可以假定构造A的实例,函数返回值在调用端绑定到该实例。这既不会导致移动,也不会导致复制构造。如果返回的对象有名称,则可以乐观地假设相同的行为,只要func()没有使NRVO变得不可能的分支。
作为该准则的一个例外,同时也是函数参数的函数返回值不符合返回值优化的条件。因此,在A是可移动构造的情况下,移动/转发它们以防止复制:
A func(A& a) { return std::move(a);}
因此,由func(A&)的返回值创建的对象将是move-constructed.
void f1(A a1) {A a2{std::move( a1) };};void f2(A& a1){ /*同上。*/ };void f1(A&& a1) { /*再次,相同。*/ };
如果A具有移动函数,则实例a2是移动构造的,否则为copy。
除了上面的范例案例之外,还有很多需要发现的地方,我既不能深入到更多的细节,也不能满足答案的简单性。此外,当您不知道您正在处理的类型时,场景也会有所不同,例如在函数或类模板中。在这种情况下,关于如何处理复制或移动的相关不确定性的很好的读物是Eff中的第29项。现代C++ (“假设移动操作不存在,不便宜,不使用”)。
https://stackoverflow.com/questions/51998723
复制相似问题