2010-06-24 6 views
1

Je crée plusieurs fois que j'utilise la classe DataBuffer dans de nombreux endroits dans le code, elle devrait donc être rapide et légère. De plus j'utilise différentes tailles de tampon, afin de réduire les allocations de mémoire que j'ai écrit ce modèle:Question à propos de rvalue en C++ 0x

template<unsigned int T_buffer_size> class DataBuffer 
{ 
    public: 
     DataBuffer (const unsigned int &buffer_size); 

     char buffer [T_buffer_size]; 
     const unsigned int buffer_size; 
}; 

Le problème est que je dois copier DataBuffer objets plusieurs fois. C'est pourquoi je me demande si le constructeur de déménagement peut aider ici. Existe-t-il un moyen facile de déplacer mon tableau 'buffer' entre les objets?

Il est facile de mettre en œuvre cette classe:

class DataBuffer 
{ 
    public: 
     DataBuffer (const unsigned int &buffer_size); 

     char *buffer; 
     const unsigned int buffer_size; 
}; 

Mais parce que « tampon » est un pointeur régulier, il prend plus de temps pour accéder aux données stockées à l'intérieur ...

+2

Je suis confus, pourquoi est-il passé une taille de tampon deux fois? – GManNickG

+2

@GMan: Il suffit de regarder son pseudo. il a gaffé. – sbi

+1

Évitez de passer des types primitifs par référence dans les appels de fonction (sauf si vous avez réellement besoin d'une référence). Cela ne rendra pas votre code plus facile à lire ni plus rapide. Cela pourrait en fait le rendre plus lent et étrange pour le lecteur occasionnel. –

Répondre

1

Mais parce que « tampon » est un pointeur régulier, il prend plus de temps pour accéder à données stockées à l'intérieur ...

Je pense que vous vous trompez. Accéder à un tableau sur le tas n'est pas nécessairement plus lent que d'en accéder un sur la pile, par ex. La vraie différence sera dans la création et la destruction du tableau.

Vous ne pouvez pas vraiment l'avoir dans les deux sens, directement (mais lisez plus loin). Si votre DataBuffer alloue sur le tas, il paiera le prix de l'allocation et de la désallocation basées sur le tas, mais vous pourrez échanger les données et implémenter quelque chose comme un constructeur de mouvement (voir le mojo d'Alexandrescu comme une simple proposition de le problème). S'il alloue des données sur la pile, il sera très rapide à créer et à détruire, mais devra copier en profondeur les données, ce qui peut être un peu cher (bien que memcpy soit terriblement rapide et parfaitement bien pour un tampon char). Cependant, vous pouvez obtenir le meilleur des deux mondes en écrivant votre propre allocateur de mémoire. Je ne recommande de le faire que si vous voulez vraiment y mettre l'effort et avoir vu, avec l'aide du profileur, qu'il s'agit d'un véritable goulot d'étranglement. Je n'ai pas le temps ou la place pour vous apprendre ceci ici, mais je dois vous avertir que ce n'est pas aussi trivial que cela semble en écrire un (considérez l'alignement comme un exemple).

La détermination de si vous allez pour le premier exemple ou le second doit être dictée principalement par si vous pouvez toujours déterminer la taille de la mémoire tampon au moment de la compilation. Si c'est le cas, optez pour la première solution car elle permet d'allouer le tampon sur la pile ou le tas. Vous pouvez toujours échanger des données peu profondes en faisant:

DataBuffer<some_size>* d1 = new DataBuffer<some_size>; 
DataBuffer<some_size>* d2 = 0; 
std::swap(d1, d2); 

... ou pour des exemples plus sophistiqués, vous pouvez utiliser des choses comme boost :: shared_ptr.

2

Est-il facile façon de déplacer mon tableau 'buffer' entre les objets * (char buffer [T_buffer_size];)?

Pas, vous devez copier (althrough vous pouvez utiliser en toute sécurité memcpy(...) ce qui est assez rapide) comme alloué sur la pile, et non un pointeur. Seuls les pointeurs/objets alloués sur le tas peuvent tirer parti de l'optimisation rvalue.

Mise à jour: En regardant le code, vous pouvez réécrire comme:

template<unsigned int T_buffer_size> class DataBuffer 
{ 
    public: 
     DataBuffer(); 
     char buffer [T_buffer_size]; 
}; 
+0

Ce n'est pas alloué sur la pile (nécessairement), c'est dans la classe. Il utilise donc l'allocateur utilisé pour l'instance de classe. –

+0

Ben: disons que c'est STATUELLEMENT alloué –