38 votes

Est spécialisée std::swap obsolète maintenant que nous avons la sémantique de déplacement?

Double Possible:
La sémantique de déplacement == custom fonction d'échange obsolète?

C'est combien de std::swap ressemble au C++11:

template<typename T>
void swap(T& x, T& y)
{
  T z = std::move(x);
    x = std::move(y);
    y = std::move(z);
}

Dois-je continuer à se spécialiser std::swap pour mes propres types, ou seront - std::swap être aussi efficace qu'elle obtient, à condition que les élèves de ma classe définit un constructeur de déplacement et un opérateur d'assignation de déplacement, de cours?

35voto

Howard Hinnant Points 59526

La spécialisation de l' std::swap est désormais facultative, mais pas obsolète. La justification est la performance.

Pour le prototypage de code, et peut-être même pour beaucoup de code de la navigation, std::swap sera beaucoup rapide. Toutefois, si vous êtes dans une situation où vous avez besoin de eek tous peu à partir de votre code, l'écriture d'un personnalisé swap peut-être encore un avantage de performance significative.

Considérons le cas où votre classe est essentiellement un propriétaire de pointeur et de votre constructeur de déplacement et d'assignation de déplacement juste avoir à traiter avec un pointeur. Le comte de la machine charges et les stocke pour chaque membre:

Constructeur de déplacement: 1 chargez et 2 magasins.

Assignation de déplacement: 2 charges et 2 magasins.

Personnalisé swap: 2 charges et 2 magasins.

std::swap est de 1 déplacez la construction et de 2 déplacez les affectations ou les: 5 charges et 6 magasins.

Une coutume swap est potentiellement encore deux ou trois fois plus rapide que l' std::swap. Si toute fois vous êtes à essayer de comprendre la vitesse de quelque chose en comptant les charges et les magasins, les deux vont être méchant rapide.

Remarque: Dans le calcul du coût de votre déménagement affectation, assurez-vous de prendre en compte que vous allez être en mouvement dans un déplacé-de valeur (en std::swap de l'algorithme). Souvent, cela annule le coût d'une libération, mais au prix d'une branche.

4voto

utnapistim Points 12060

Est spécialisée std::swap obsolète maintenant que nous avons la sémantique de déplacement?

Pas de. C'est la version générique, mais vous pouvez l'optimiser pour passer d'un troisième opération de déplacement. Ma préférence est de combiner copie&swap idiome de la personnalisation de std::swap pour mes cours.

Cela signifie que je vais avoir:

class Aaaa
{
public:
    Aaaa(); // not interesting; defined elsewhere
    Aaaa(Aaaa&& rvalueRef); // same
    Aaaa(const Aaaa& ref); // same
    ~Aaaa(); // same
    Aaaa& operator=(Aaaa object) // copy&swap
    {
        swap(object);
        return *this;
    }
    void swap(Aaaa& other)
    {
        std::swap(dataMember1, other.dataMember1);
        std::swap(dataMember2, other.dataMember2);
        // ...
    }

    // ...
};

namespace std
{
    template<> inline void std::swap(Aaaa& left, Aaaa& right)
    { left.swap(right); }
}

0voto

PlasmaHH Points 8426

Cela dépendra de votre Type.

Vous pourrez le déplacer de x à z, à partir de y à x, de z à y. C'est trois opérations de copie de la représentation sous-jacente (peut-être seulement un pointeur, peut-être quelque chose de plus, qui sait)

Maintenant peut-être vous pouvez créer une plus rapide swap pour votre type (xor swap trick, assembleur en ligne, ou peut-être std::swap pour votre sous-jacente types est juste plus rapide).

Ou peut-être aussi votre compilateur est bon à optimiser, et essentiellement optimise les deux cas, dans les mêmes instructions (comme ont temporaire dans un registre).

Personnellement, j'ai tendance à toujours mettre en œuvre un swap de membre de la fonction qui va être appelée à partir de plusieurs endroits, y compris des choses comme le mouvement d'affectation, mais YMMV.

0voto

ali_bahoo Points 2676

Cette swap() appelle un constructeur de déplacement et de 2 déplacez les affectations. Je pense que l'on peut écrire plus efficace, swap() de son type particulier de classe,

class X
{
    int * ptr_to_huge_array;
public:
// ctors, assgn ops. etc. etc.

    friend void swap(X& a, X& b)
    {
        using std::swap;
        swap(a.ptr_to_huge_array, b.ptr_to_huge_array);
    }
};

indépendamment de la mise en œuvre de déplacer le constructeur et l'opérateur d'affectation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X