GNT sans publicité, site mobile, fonctionnalitées exclusives...

Conteneur séquentiel et transformation

Le
Mickaël Wolff
Bonjour,

Quelle est la raison fondamentale pour laquelle std::transform
nécessite une séquence de sortie pré-dimensionnée ?

Par exemple:

#include <vector>

int main()
{
int ref[] = { 1, 36, 69, 42 } ;

std::vector<int> reference ;
reference.resize(sizeof ref / sizeof *ref) ;

std::transform(ref, ref + reference.size(), reference.begin()) ;
}

Si je n'ajuste pas reference, il reste vide. Dans un exemple plus
complexe, j'ai du segfault: avec des shared_ptr, swap tente d'échanger
le pointeur courant avec le pointeur courant d'un emplacement mémoire
qui n'est pas un shared_ptr.

Je comprends que std::transform ne redimensionne pas mon std::vector
de destination. La raison est-elle qu'on paye pour ce qu'on utilises ?

Au plaisir de vous lire.
--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Lire les 35 réponses

Vidéos High-Tech et Jeu Vidéo
Téléchargements
Vos réponses Page 1 / 7
Gagnez chaque mois un abonnement Premium avec GNT : Inscrivez-vous !
Trier par : date / pertinence
Fabien LE LEZ
Le #22452211
On Sun, 08 Aug 2010 03:52:58 +0100, Mickaël Wolff

Je comprends que std::transform ne redimensionne pas mon std::vector
de destination.



Comment le pourrait-il ? Tu ne lui passes pas le vector en question,
mais juste un itérateur.

Jette un coup d'oeil là-dessus :
http://www.cplusplus.com/reference/..._inserter/
Gabriel Dos Reis
Le #22453121
Mickaël Wolff
| Bonjour,
|
| Quelle est la raison fondamentale pour laquelle std::transform
| nécessite une séquence de sortie pré-dimensionnée ?
|
| Par exemple:
|
| #include <vector>
|
| int main()
| {
| int ref[] = { 1, 36, 69, 42 } ;
|
| std::vector<int> reference ;
| reference.resize(sizeof ref / sizeof *ref) ;
|
| std::transform(ref, ref + reference.size(), reference.begin()) ;
| }

template<typename T, int N>
int size(const T(&) [N]) { return N; }

template<typename T, int N>
T* begin(const T(&ary) [N]) { return &ary[0]; }

template<typename T, int N>
T* end(const T(&ary) [N]) { return &ary[0] + N; }

int main()
{
int ref[] = { 1, 36, 69, 42 } ;

std::vector<int> reference(size(ref));
std::copy(begin(ref), end(ref), reference.begin());
}


|
| Si je n'ajuste pas reference, il reste vide. Dans un exemple plus
| complexe, j'ai du segfault: avec des shared_ptr, swap tente d'échang er
| le pointeur courant avec le pointeur courant d'un emplacement mémoire
| qui n'est pas un shared_ptr.

std::vector<int> reference;
std::copy(begin(ref), end(ref), std::back_inserter(reference));

| Je comprends que std::transform ne redimensionne pas mon std::vector
| de destination. La raison est-elle qu'on paye pour ce qu'on utilises ?

Orthogonalité.
La fonction de transform, c'est de transformer les éléments de la suite,
pas de changer la taille de la destination.

-- Gaby
Mickaël Wolff
Le #22453301
Le 08/08/2010 06:38, Fabien LE LEZ a écrit :

Comment le pourrait-il ? Tu ne lui passes pas le vector en question,
mais juste un itérateur.



Justement, c'est un truc que je ne comprends toujours pas. Comment un
itérateur peut à la fois référencer un conteneur et ne pas y avoir accès ?

Dans l'implémentation, un itérateur doit bien conserver des
références vers le conteneur. Rien que pour pouvoir progresser dans la
collection. Du coup, à l'instar d'un pointeur habile, il pourrait
fournir une fonction membre vers le conteneur itéré ? Ou encore une fois
c'est une question de découplage ?

Merci !

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Mickaël Wolff
Le #22453371
Il semblerait que ce message ne soit pas passé. Je réitère donc.

Le 08/08/2010 16:53, Gabriel Dos Reis a écrit :

template<typename T, int N>
int size(const T(&) [N]) { return N; }



Rien que pour ça j'ai bien fait de poser la question. Je n'y aurais
pas pensé.

std::vector<int> reference;
std::copy(begin(ref), end(ref), std::back_inserter(reference));



En fait, j'ai trouvé cette réponse quelques minutes après avoir posé
la question dans le bouquin (Effective STL, Scott Meyers) que je lis (et
qui m'a mené à l'observation de std::transform). Mais ça ne répondait
toujours pas à mon interrogation profonde.


| Je comprends que std::transform ne redimensionne pas mon std::vector
| de destination. La raison est-elle qu'on paye pour ce qu'on utilises ?

Orthogonalité.
La fonction de transform, c'est de transformer les éléments de la suite,
pas de changer la taille de la destination.



Ok, c'est ce que je pensais : un problème de responsabilité. Bon, ben
c'est le memcpy du C++ :)

Merci!

--
Mickaël Wolff aka Lupus Michaelis
http://lupusmic.org
Alexandre Bacquart
Le #22453811
On 08/08/2010 08:43 PM, Mickaël Wolff wrote:
Le 08/08/2010 06:38, Fabien LE LEZ a écrit :

Comment le pourrait-il ? Tu ne lui passes pas le vector en question,
mais juste un itérateur.



Justement, c'est un truc que je ne comprends toujours pas. Comment un
itérateur peut à la fois référencer un conteneur et ne pas y avoir accès ?



Un iterator référence un élément du conteneur, pas le conteneur
lui-même. Tu connais bien C si je ne m'abuse, ça ne te rappelle rien ?

Dans l'implémentation, un itérateur doit bien conserver des références
vers le conteneur.



Ha bon ? Pourquoi ?

Rien que pour pouvoir progresser dans la collection.



Un pointeur a-t-il besoin de référencer le tableau contenant l'élément
pointé pour progresser dans ce tableau ?

Du coup, à l'instar d'un pointeur habile, il pourrait fournir une
fonction membre vers le conteneur itéré ?



Ca, c'est un pointeur très habile !

Ou encore une fois c'est une question de découplage ?



Comme pour un pointeur. La sémantique est d'ailleurs étrangement proche,
non ? Itérateur ou pointeur, on dirait parfois le même objet, mais
déclaré différemment...


--
Alex
Publicité
Suivre les réponses
Poster une réponse
Anonyme