2013-01-23 5 views
2

J'ai un code simple:liste de capture Lambda et la copie

#include <iostream> 
#include <functional> 

struct Copy 
{ 
    Copy(){} 
    Copy(const Copy&) 
    { 
     std::cout << "Copied!\n"; 
    } 
}; 

int main() 
{ 
    Copy copy; 
    std::function<void()> func = [=]{(void)copy;}; 
    return 0; 
} 

Et il appelle 2 fois la copie cteur et je veux avoir qu'une seule fois. Je comprends que je peux utiliser l'auto dans cet exemple simplifié, mais j'ai besoin de le stocker pour une utilisation ultérieure, donc auto n'est pas une option. Et ma question: est-il un moyen de stocker lambda avec = liste de capture et avoir une seule copie des objets capturés?

+0

Je suis surpris l'instance est copiée, comme la fonction que vous créez ne soit pas réellement appelé . Quel compilateur et quelle version utilisez-vous? –

+0

@JoachimPileborg: Bien sûr, il y a deux copies: l'une pour copier 'copy' dans le lambda, et l'autre qui se produit quand le lambda (qui a un membre' Copy') est copié dans la fonction 'std :: function'. – Mankarse

Répondre

4

Il y a deux copies: une pour copier copy dans le lambda, et qui se produit lorsque est copié dans le std::function lambda (qui comporte un élément Copy).

Si vous voulez une copie et un mouvement, vous devrez faire l'objet Copy être mobile:

#include <iostream> 
#include <functional> 

struct Copy 
{ 
    Copy(){} 
    Copy(const Copy&) 
    { 
     std::cout << "Copied!\n"; 
    } 
    Copy(Copy&&) 
    { 
     std::cout << "Moved!\n"; 
    } 
}; 
//Prints: 
//Copied! 
//Moved! 
int main() 
{ 
    Copy copy; 
    std::function<void()> func = [=]{(void)copy;}; 
    return 0; 
} 
+0

est-ce que cela se fait par norme? Je veux dire que lambda doit avoir move-ctor/operator =? – ixSci

+0

@ixSci: Oui - voir '[expr.prim.lambda]/19':" Le type de fermeture associé à une expression lambda a un constructeur par défaut supprimé (8.4.3) et un opérateur d'affectation de copie supprimé. constructeur de copie implicitement déclaré (12.8) et peut avoir un constructeur de mouvement implicitement déclaré (12.8) [Note: Le constructeur de copie/déplacement est implicitement défini de la même manière que tout autre constructeur de copie/déplacement implicitement déclaré serait implicitement défini. - note de fin] ". (Merci de demander cependant, la note sur 'mutable' était fausse) – Mankarse

+0

merci Mankarse! Je suis un peu confus par le "peut avoir un constructeur de mouvement implicitement déclaré", cependant. GCC et Clang l'ont et MSVC ne l'a pas. Et je ne suis pas sûr que je puisse classer le bogue puisque ce comportement n'est pas forcé par le standard mais simplement "n'est pas interdit" – ixSci

Questions connexes