2017-06-15 3 views
0

Ceci est probablement assez similaire à d'autres questions; J'ai regardé autour de moi mais je ne sais pas de quoi je parle assez pour être sûr. J'écris une fonction qui "devrait" être en place, mais qui est implémentée par un appel BLAS. L'appel BLAS n'est pas en place, j'ai donc besoin de faire un temporaire. Ainsi:std :: move pour "opération sur place"

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); 
} 

Est-ce une utilisation valable de std::move, ou suis-je rompent en quelque sorte « copie élision » (ou est-ce mauvais pour une autre raison)? Edit: la signature de CallBLASDgemm a été demandée; c'est

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

c'est bon. mais si 'ArrayClass' ne supporte pas l'assignation de déplacement, vous le copieriez tout de même. –

+2

Quelle est la signature de 'CallBLASdgemm'? –

Répondre

2

Aucune copie n'est effectuée avec ou sans copie dans ce cas, ce qui est déjà hors de question. Parce que U_temp est un lvalue le compilateur doit appeler le constructeur de copie si vous faites:

U = U_temp; 

Cependant, vous savez que U_temp ne sera pas utilisé plus et donc se éloigner de ses valeurs est complètement sûr et peut éventuellement être plus rapide (c'est-à-dire si ArrayClass implémente un constructeur d'assignation de mouvement). En utilisant std::move ici est très bien et même encouragé.

+1

@TobySpeight Je ne peux jamais sembler avoir raison, merci. –

2

Oui, ceci est un cas d'utilisation valide. Si vous avez un nom temporaire (lvalue), la seule façon de le déplacer en U est d'utiliser std::move pour le convertir en valeur rvalue.

Je pense que ce qui vous inquiète, c'est quand les gens font return std::move(object);. C'est une pessimisation car cette copie de l'objet dans la valeur de retour peut être élidée dans la plupart des cas.

1

Ceci est valide. Cependant, ce que je ferais est la suivante:

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); 
} 

qui exécute le même code, mais est-ce sans être temporaire visible dans le champ extérieur.

En fait, myCallBLASdgemm est si propre que vous pouvez probablement éliminer InPlace et appelez simplement myClassBLASdgemm où vous en avez besoin.