rvalue reference

rvalue reference - C++ - Programmation

Marsh Posté le 28-02-2009 à 15:14:27    

Allo,
 
A quoi sert cette notion en C++ ?
 
La syntaxe est la suivante : A && a;
Merci.

Message cité 1 fois
Message édité par weblook$$ le 28-02-2009 à 15:42:13
Reply

Marsh Posté le 28-02-2009 à 15:14:27   

Reply

Marsh Posté le 28-02-2009 à 15:23:53    

y a l'air d'avoir un bon article à ce sujet :
http://blogs.msdn.com/vcblog/archi [...] art-2.aspx

Reply

Marsh Posté le 28-02-2009 à 16:12:12    

weblook$$ a écrit :

A quoi sert cette notion en C++ ?


 
Permettre d'avoir un comportement particulier quand une fonction reçoit un temporaire (par opposition à une variable).  Deux utilisations parmi d'autres: des opérations de déplacement, où on récupère ce qui est déjà fait et qui aurait été détruit -- c'est parfois une question de perf mais pas toujours, par exemple ça permet d'éviter les gros hacks qui permettent à une fonction de retourner un std::auto_ptr -- et surcharger en permettant de lier des temporaires à une référence (de rvalue) non constante.  Pour éviter le classique:
 

Code :
  1. std::ofstream(logFile.c_str(), "a" ) << "Voici un comportement inattendu\n";


 
qui met 0xDEADBEAF dans le fichier plutôt que la chaîne.

Reply

Marsh Posté le 28-02-2009 à 16:24:58    

La notion de constructeur  de déplacement (il me semble) revient souvent autour du concept de rvalue reference, pourrais-tu me dire en quoi sont elles liées? je devine qu'il s'agit là de l'idée de gain en  performance que tu as évoqué dans ta réponse

Message cité 1 fois
Message édité par weblook$$ le 28-02-2009 à 16:29:55
Reply

Marsh Posté le 28-02-2009 à 16:31:04    

weblook$$ a écrit :

La notion de constructeur  de déplacement (il me semble) revient souvent autour de cette notion, pourrais-tu me dire en quoi sont elles liées?


 

Un Programmeur a écrit :


des opérations de déplacement, où on récupère ce qui est déjà fait et qui aurait été détruit -- c'est parfois une question de perf mais pas toujours, par exemple ça permet d'éviter les gros hacks qui permettent à une fonction de retourner un std::auto_ptr


 
Si tu en veux plus, il faut faire tout un cours sur ça.  Et j'ai pas envie
et les forums ne me semblent pas le lieu le plus adéquat, si j'en avais
envie, ça partirait sur un site ou dans un bouquin.

Reply

Marsh Posté le 28-02-2009 à 16:42:14    

d'accord merci

Reply

Marsh Posté le 06-03-2009 à 14:00:58    

mais en fait comment le compilateur c'est qu'il doit appeler le constructeur de move plutot que le constructeur de recopie ??

Reply

Marsh Posté le 06-03-2009 à 14:16:43    

Le constructeur de copie est utilise pour les lvalues, celui de deplacement pour les rvalues.

Reply

Marsh Posté le 06-03-2009 à 14:20:26    

parfait merci

Reply

Marsh Posté le 21-03-2009 à 22:16:06    

big up pour les paumés de la rvalue-référence [:mulder]

Reply

Marsh Posté le 21-03-2009 à 22:16:06   

Reply

Marsh Posté le 21-03-2009 à 22:20:08    

Un Programmeur a écrit :

Code :
  1. std::ofstream(logFile.c_str(), "a" ) << "Voici un comportement inattendu\n";


qui met 0xDEADBEAF dans le fichier plutôt que la chaîne.


 
Ah bon ?
 
C'est

Code :
  1. std::ofstream(logFile.c_str(), "a" ).operator<<( "Voici un comportement inattendu\n" );


La chaine est une constante littérale, sa durée de vie est celle du programme, je ne vois pas où est le bug !

Reply

Marsh Posté le 21-03-2009 à 23:50:49    

c'est sans doute dû au faite que l'objet ofstream est un temporaire justement, mais j'avoue être incapable de comprendre le pourquoi du comment ça ne marche pas


---------------

Reply

Marsh Posté le 22-03-2009 à 09:40:30    

[quotemsg=1864418,11,23947]
 
Ah bon ?
 
C'est

Code :
  1. std::ofstream(logFile.c_str(), "a" ).operator<<( "Voici un comportement inattendu\n" );

[/quote]
 
C'est bien ce que c'est mais c'est pas ce qu'on voudrait...
 
L'opérateur prenant un void* est un membre, l'opérateur prenant un char const* est un opérateur libre.  Le
temporaire.  Or on peut appeler un membre non const sur un temporaire qui ne l'est pas (il est des temporaires
qui sont const, en retour de fonction par exemple), mais pas binder un temporaire à une référence non const.
Donc l'opérateur prenant un char const* n'est pas un candidat valable et c'est celui prenant un void* qui est
choisi.

Reply

Marsh Posté le 22-03-2009 à 11:16:00    

Comment se prendre la tête 10 ans avant que ça sorte. Tu sais déjà pas écrire une classe correcte, y a certainement mieux à voir avant des trucs futurs.

Reply

Marsh Posté le 22-03-2009 à 13:33:32    

Taz a écrit :

Comment se prendre la tête 10 ans avant que ça sorte. Tu sais déjà pas écrire une classe correcte, y a certainement mieux à voir avant des trucs futurs.


si c'est pour moi, ben ué c'est bien pour ça que je me sers des forum pour poser des questions pour tenter d'en savoir un peu plus...


---------------

Reply

Marsh Posté le 22-03-2009 à 19:22:21    

je te défends weblook$$, je ne vois pas où est le mal à poser des questions poliement, il ne me semble pas qu'il faille étaler du code de l33t ici pour pouvoir poser une question un peu avancée.
 
pour l'opérateur<<, le fait que ce soit une free function ou un opérateur n'est-il pas laissé à l'éprécisation de l'implémentation ? Généralement le standard est très souple dès qu'il y a 2 façons équivalente de coder un truc. En tout cas j'aurais appris un truc dans la catégorie bizarrerie syntaxique du c++ :D

Reply

Marsh Posté le 22-03-2009 à 23:35:38    

en general, si tu peut t'en passer, tu te passes de friend.

Reply

Marsh Posté le 24-03-2009 à 17:21:40    

Un Programmeur a écrit :

[quotemsg=1864418,11,23947]  (il est des temporaires
qui sont const, en retour de fonction par exemple), .


 
c'est koi un temporaire const en retour de fonction ?  

Code :
  1. const int & f()
  2. {
  3. const int nb;
  4. return nb;
  5. }


 
?


---------------

Reply

Marsh Posté le 24-03-2009 à 17:45:19    

Une reference n'est pas un temporaire.
 

Code :
  1. class C;
  2. C const f();

Reply

Marsh Posté le 24-03-2009 à 19:55:07    


Code :
  1. std::ofstream(logFile.c_str(), "a" ).operator<<( "Voici un comportement inattendu\n" );

 

mais pas binder un temporaire à une référence non const. Donc l'opérateur prenant un char const* n'est pas un candidat valable et c'est celui prenant un void* qui est choisi

 


Dans cet exmple où est la référence non const??


Message édité par weblook$$ le 24-03-2009 à 19:55:39

---------------

Reply

Marsh Posté le 24-03-2009 à 22:24:11    

Un Programmeur a écrit :

Une reference n'est pas un temporaire.
 

Code :
  1. class C;
  2. C const f();



et puis il me semblait que la définition d'un temporaire était une variable qui n'avait pas de nom...


---------------

Reply

Marsh Posté le 25-03-2009 à 01:56:00    

Un Programmeur a écrit :

[quotemsg=1864418,11,23947]
 mais pas binder un temporaire à une référence non const.
Donc l'opérateur prenant un char const* n'est pas un candidat valable et c'est celui prenant un void* qui est
choisi.

 

pourtant dans ce genre de code on bind bien un temporaire à référence non const :

 
Code :
  1. struct A
  2. {
  3. A(){}
  4. A(const A& a){}
  5. A& operator = (A& var) //bindage, var reçoit bien un temporair non?
  6. {
  7. }
  8. };
  9. A f(A a)
  10. {
  11. return a;
  12. }
  13. A a;
  14. a=f(a) //f(a) = temporaire non ?


Message édité par weblook$$ le 25-03-2009 à 02:04:42

---------------

Reply

Marsh Posté le 25-03-2009 à 07:42:04    

ca compile pas ça je pense :o

 
Citation :


test.cpp: In function 'int main()':
test.cpp:18: error: no match for 'operator=' in 'a = f(A)()'
test.cpp:5: note: candidates are: A& A::operator=(A& )


Message édité par Joel F le 25-03-2009 à 07:46:53
Reply

Marsh Posté le 25-03-2009 à 10:09:12    

sous visual dernière mouture ça passe en tous cas


---------------

Reply

Marsh Posté le 25-03-2009 à 10:36:57    

bah c'ets un peu une connerie

Reply

Marsh Posté le 25-03-2009 à 10:38:31    

Code :
  1. struct A
  2. {
  3. unsigned char * n;
  4. int nb;
  5. A(){}
  6. A(const A& a)
  7. {
  8. }
  9. A& operator = (A& a)
  10. {
  11.  n=(unsigned char*)&a;
  12.  ((A*)n)->nb=9;
  13.  return *this;
  14. }
  15. };
  16. A f(A a)
  17. {
  18. return a;
  19. }
  20. int main()
  21. {
  22. A a;
  23. cout << ((A*)((a=f(a)).n))->nb;
  24. }
 

d('autant plus que le temporaire existe encore après la fin de =, c'est space


Message édité par weblook$$ le 25-03-2009 à 10:41:01

---------------

Reply

Marsh Posté le 25-03-2009 à 11:53:34    

VC++ n'a jamais été la norme des compilos faut dire :s

Reply

Marsh Posté le 25-03-2009 à 13:46:38    

weblook$$ a écrit :

sous visual dernière mouture ça passe en tous
cas


 
Il est un peu anachronique. Bjarne Stroustrup dans The Design and
Evolution of C++
(1994, p 86) ecrit
 

Citation :

I made one serious mistake, though, by allowing a non-const
reference to be initialized by a non-lvalue.  For exemple:

Code :
  1. void incr(int& rr) { rr++; }
  2. void g()
  3. {
  4.     double ss = 1;
  5.     incr(ss);    // note: double passed, int expected
  6.                  // (fixed: error in Release 2.0)
  7. }


Because of the difference in type the int& cannot refer to the double
passed so a temporary was generated to hold an int initialized by ss's
value.  Thus incr() modified the temporary, and the result wasn't reflected
back to the calling function.
 
The reason to allow references to be initialized by non-lvalues was to
allow the distinction between call-by-value and call-by-reference to be a
detail specified by the called function and of no interest to the caller.
For const references, this is possible; for non-const references it is not.
For Release 2.0 the definition of C++ was changed to reflect this.


 
La Release 2.0, date de juin 1989.

Reply

Marsh Posté le 25-03-2009 à 16:54:32    

sous visual ça ne passe pas ça par contre, tant mieux donc


---------------

Reply

Marsh Posté le 26-03-2009 à 23:41:13    

Joel F a écrit :

VC++ n'a jamais été la norme des compilos faut dire :s


il s'est énormément amélioré, et Visual 2008 est très proche de la norme, même si GCC reste la référence.
La mauvaise réputation de VC++ vient surtout de VC 6, qui n'était pas à la norme, et de la STL livrée avec.
VC6 date de 1997 (c'est le compilateur qui a compilé Windows 98) donc il ne risquait pas d'être à la norme. D'ailleurs pour un compilo de 97, je trouve qu'il s'en sortais pas trop mal.
La STL livrée était celle de Visual 5, pour des raisons de licences MS n'a pas eu le droit de livrer la bonne STL qui allait avec (VC6 supportait les membres template par exemple alors que ça STL ne s'en servait pas).

Reply

Marsh Posté le 27-03-2009 à 00:48:55    

D'ailleurs quel est la ou les raison(s) qui fait que visual ne suit pas la norme ?  


---------------

Reply

Marsh Posté le 27-03-2009 à 12:46:28    

c'est par facilité ou c'est de l'incompétence


---------------

Reply

Marsh Posté le 29-03-2009 à 18:38:25    

Visual C++ 6.0, pour deux raisons :
- Il date d'avant la norme, donc il aurait eu du mal à y être conforme.
- A cette époque, Visual C++ devait plutôt servir pour des produits/technos spécifiques à Microsoft, comme MFC ou MIDL. Il ne devait pas trop servir comme compilateur C++ pur, microsoft considérait ces langages comme plutôt réservés au monde Unix.
 
Puis .NET est arrivé pour mettre tout ça au propre, et là microsoft a changé de point de vue : Ceux qui voulait faire de la technos windows, ils feraient du .NET, donc du C# ou du managed C++.
Les développeurs qui continueraient à utiliser Visual comme compilo C++ pur, seraient alors ceux qui auraient besoin de portabilité, ou qui voulaient utiliser un langage standard, et pas se restreindre à une techno microsoft. Donc des gens qui avaient besoin d'un compilateur respectant le standard. C'est pour celà qu'à partir de Visual 2002, la norme est aussi bien respectée qu'avec les autres compilos.
 
VC++ n'est pas encore au niveau de GCC, mais il est très proche du standard, et il s'améliore sans cesse. VC++ 2008 est une très très bonne implémentation du langage.
Quand ce n'est pas le cas, c'est surtout parce que le C++ a une syntaxe parfois complexe que même les créateurs de compilateurs ont du mal à implémenter. Déclarer friend un membre template de classe template c'est par exemple une syntaxe tellement lourde que beaucoup de compilos ne s'en sortent pas.
 
Généralement c'est une erreur de conception sur un point complexe du langage. Parfois c'est une grosse bourde idiote. Pa exemple :
template< class T >
T build( int n ) { return T( n ); }
 
Ca ne marche pas sous VC6 car les concepteurs ont oublié d'inclure les paramètres du template dans la signature de la fonction, ce qui fait échouer le linker. C'est pourtant un bout de code très simple.


Message édité par jesus_christ le 29-03-2009 à 18:39:47
Reply

Marsh Posté le 29-03-2009 à 20:30:23    

intéressant merci bien


---------------

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed