std :: move for“就地操作”

时间:2017-06-15 16:51:55

标签: c++ c++11 move move-semantics

这可能与其他问题非常相似;我环顾四周,但我不知道我说的是什么,以确保。

我正在编写一个“应该”就地的功能,但这是通过BLAS调用实现的。 BLAS呼叫不到位,所以我需要做一个临时的。因此:

void InPlace(ArrayClass& U, const TransformMatrix* M){
    ArrayClass U_temp; 
    CallBLASdgemm(U, M, U_temp);   //Now U_temp contains the correct output.
    U = std::move(U_temp);
}

这是std::move的有效用途,还是我在某种程度上打破了“复制省略”(或者由于其他原因而不好)?

编辑:请求CallBLASDgemm的签名;它是

CallBLASdgemm(const ArrayClass& U, const TransformMatrix* M, 
              ArrayClass& V);

3 个答案:

答案 0 :(得分:2)

是的,这是一个有效的用例。如果您有一个命名临时(左值),将其移至U的唯一方法是使用std::move将其转换为右值。

我认为你担心的是人们做return std::move(object);的时候。这是一种悲观,因为在大多数情况下,可以省略将对象复制到返回值中。

答案 1 :(得分:2)

在这种情况下,无论是否使用复制省略都不会执行复制,因此已经无法解决问题。因为U_temp是左值,所以如果你这样做,编译器必须调用拷贝构造函数:

U = U_temp;

但是,您知道U_temp不再被使用,因此移除其值是完全安全的,并且可能更快(即,如果ArrayClass实现了移动赋值构造函数)。在这里使用std::move很好,甚至鼓励。

答案 2 :(得分:1)

这是有效的。但是,我要做的是:

ArrayClass myCallBLASdgemm(const ArrayClass& U, const TransformMatrix* M) {
  ArrayClass tmp;
  CallBLASdgemm(U, M, tmp);
  return tmp; // elided move
}
void InPlace(ArrayClass& U, const TransformMatrix* M){
  U = myCallBLASdgemm(U, M);
}

运行相同的代码,但是在外部作用域中没有临时可见的情况。

事实上,myCallBLASdgemm非常干净,您可以删除InPlace,只需在需要的地方拨打myClassBLASdgemm