Les petites structures simples doivent-elles être passées par référence const?

On m’a toujours enseigné que les types non primitifs devraient être passés par référence const plutôt que par valeur si possible, c’est-à-dire

void foo(std::ssortingng str);//bad void foo(const std::ssortingng &str);//good 

Mais je pensais aujourd’hui qu’il serait peut-être préférable de passer certains types simples définis par l’utilisateur, par exemple:

 class Vector2 { public: float x, y; ...constructors, operators overloads, utility methods, etc... }; void foo(Vector2 pos); void foo(const Vector2 &pos);//is this really better than by value? void foo(float x, float y);//after all isn't by value effectively doing this? 

Je pense qu’en passant Vector2 par référence, il est en fait plus coûteux que de passer en valeur puisque le compilateur utilise maintenant un pointeur et le déréférencement pour accéder à la version const Vector2 & pos?

Est-ce le cas? Les objects simples sont-ils mieux passés par valeur? Où faut-il tracer la ligne?

Oui, les objects simples doivent être passés par valeur. La ligne doit être tracée en fonction de l’architecture. En cas de doute, profilez.

Passer par référence constante évite la construction d’un nouvel object. Si votre constructeur n’est pas sortingvial, par exemple s’il alloue de la mémoire, il sera beaucoup mieux de passer par référence const que par valeur.

Dans le monde C #, vous prenez cette décision en choisissant de faire quelque chose d’une classe ou d’une structure. Les classes utilisent la sémantique de référence, tandis que les structures utilisent la sémantique de valeur. Tout ce que j’ai lu dit que vous devriez généralement choisir de faire de chaque classe une classe, sauf si elle est très petite, c’est-à-dire de l’ordre de 16 octets. Si vous recherchez une date limite pour la transmission de la valeur par rapport à la référence const en C ++, 16 octets semble être un seuil raisonnable.

Par simple politique, je passe tout object qui n’est pas un type de données C de base par référence const. C’est beaucoup plus facile de se souvenir de cette façon.

Une parsing plus ancienne, mais lucide, des entrées-sorties des parameters de passage peut être consultée à l’ adresse http://www.ddj.com/184403855 . Bien sûr, c ++ 0x évite un grand nombre de problèmes de ce type avec la sémantique du déplacement, mais le document fournit de nombreuses explications quant à la raison pour laquelle la sémantique du déplacement est souhaitable.

Un facteur que je n’ai pas vu mentionné est ce que la routine va faire avec la valeur transmise. À moins que la routine ne soit développée en ligne, la manipulation des données transmises par référence nécessitera plus de code que celle des données transmises par valeur. Si l’access aux champs de la structure transmise est en moyenne inférieur à une fois chacun, cette surcharge supplémentaire sera réduite par rapport à celle de la copie de la structure. Si, en moyenne, ils seront consultés plusieurs fois chacun, il serait probablement préférable de les avoir sur la stack. Si l’interface est déjà définie comme référence par référence pour une structure très sollicitée, il peut être judicieux que la routine appelée copie toutes les parties présentant un intérêt. D’autre part, si la routine appelée doit copier une grande partie ou la totalité d’une structure, elle peut aussi bien être passée par valeur.

Je pense qu’en passant Vector2 par référence, il est en fait plus coûteux que de passer en valeur puisque le compilateur utilise maintenant un pointeur et le déréférencement pour accéder à la version const Vector2 & pos

Ce serait vrai si vous size_of(object) < size_of(pointer_to_object) un object où size_of(object) < size_of(pointer_to_object) . Par exemple, char const& pourrait être plus cher que char