2015-08-21 4 views
1

S'il vous plaît considérer le morceau de code suivant:assurer qu'une variable membre est déplacé, si l'objet est un rvalue

class A 
{ 
public: 
    A(/* params */) { 
     // Fill m_data depending on params 
    } 

    std::vector<double> get_data() const noexcept { 
     return m_data; 
    } 

private: 
    std::vector<double> m_data; 
}; 

std::vector<double> get_data() { 
    return A{/* suitable params */}.get_data(); 
} 

Ce que je veux est que m_data est déplacé à l'appelant de la fonction get_data() , c'est-à-dire qu'aucune copie ne devrait être faite.

Comment puis-je être sûr que c'est le cas? Clairement, A{/* suitable params */} est une valeur. Par conséquent, sa variable membre m_data est un rvalue dans ce contexte. Alors, est-ce suffisant pour ajouter une autre fonction membre

std::vector<double> get_data() && noexcept { 
    return std::move(m_data); 
} 
+0

@Barry: La section de réponse est là-bas, bub: ↓↓↓↓↓↓↓ Je sais que vous savez où c'est, parce que vous y avez posté. –

+0

@Barry: Alors non –

+2

Votre version originale de 'get_data' _will_ appelera un constructeur de copie, qui pourrait lancer' bad_alloc', et dans ce cas le 'noexcept' appellera' std :: terminate() '. Peut-être que vous voulez seulement que la surcharge de rvalue sans copie soit "noexcept" –

Répondre

2

Avec un compilateur suffisamment récent (lire: non MSVC 2013), vous pouvez surcharger le rvalue vs lvalue.

class A { 
    // ... 
    std::vector<double> get_data() && noexcept { 
    return std::move(m_data); 
    } 
    std::vector<double> get_data() const & { // not noexcept, could throw 
    return m_data; 
    } 
    // ... 
}; 

Sinon, la version lvalue pourrait renvoyer une référence const au vecteur et être noexcept, mais cela signifie que vous êtes exposant le fait que vous avez une grandeur physique quelque part, ce qui vous empêche de changer qu'à l'avenir refactorisations .

Notez que vous ne pouvez pas avoir une fonction qui n'a pas de qualificatif ref et une autre fonction avec un qualificatif ref, qui ont le même nom et les mêmes paramètres. C'est ambigu, et le compilateur devrait se plaindre.