2016-02-05 1 views
2

Je voudrais implémenter une méthode "take". Une méthode "take" est quelque chose comme une méthode get, mais qui vole l'objet getté de son propriétaire: le propriétaire est laissé avec cet objet dans un état vide. Bien sûr, cela implique la sémantique de déplacement C++ 11. Mais lequel de ce qui suit est le meilleur moyen de l'implémenter?Utiliser std :: move pour une implémentation de la méthode "take"

class B 
{ 
public: 

    A take_a_1() 
    { 
     return std::move(m_a); 
    } 

    // this can be compiled but it looks weird to me that std::move 
    // does not complain that I'm passing a constant object 
    A take_a_2() const 
    { 
     return std::move(m_a); 
    } 

    A&& take_a_3() 
    { 
     return std::move(m_a); 
    } 

    // this can't be compiled (which is perfectly fine) 
    // 
    // A&& take_a_4() const 
    // { 
    //  return std::move(m_a); 
    // } 

private: 

    A m_a; 
}; 
+0

pourquoi voulez-vous le mettre à l'intérieur de B? – iggy

+1

Pas tout à fait un doublon, je pense, mais voir aussi http://stackoverflow.com/q/29504070/1858225 –

+3

Je suggère de renommer 'take' à' release' que ce nom est utilisé à des fins similaires dans les pointeurs intelligents : http://fr.cppreference.com/w/cpp/memory/unique_ptr/release –

Répondre

4

Aucune d'entre elles. J'utilise ceci:

struct B 
{ 
    A && get() && { return std::move(m_a); } 
}; 

De cette façon, vous ne pouvez « prendre » de rvalues ​​de B:

B b; 
A a = std::move(b).get(); 
+0

C'est très intéressant. Pourriez-vous expliquer pourquoi vaut mieux prendre seulement des valeurs de l'objet B entier? – nyarlathotep108

+4

@ nyarlathotep108: Eh bien, laisser l'objet derrière dans un état mutilé ne semble inconditionnellement souhaitable que si l'objet lui-même n'est plus observable (c'est-à-dire une valeur). Sinon, vous devrez spécifier une sémantique détaillée sur le fonctionnement de la prise et sur le comportement de l'objet restant. –

+1

@ nyarlathotep108 Aussi, d'une manière cruciale, puisque 'm_a' fait partie de' B', et l'état d'un objet est seulement * garanti * d'être destructible après qu'il a été déplacé de (* rien d'autre n'est garanti), 'B' l'état de 'm_a' après le déplacement est tel que, encore une fois, l'opération * only * safe est la destruction. Les fonctions qui invalident l'état d'un objet ne doivent généralement prendre que les valeurs R de cet objet, de sorte que cette invalidation d'état soit visible à partir de l'interface. –