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
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

Poser une question


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/
| 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
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
Le 08/08/2010 16:53, Gabriel Dos Reis a écrit :
Rien que pour ça j'ai bien fait de poser la question. Je n'y aurais
pas pensé.
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.
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
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 ?
Ha bon ? Pourquoi ?
Un pointeur a-t-il besoin de référencer le tableau contenant l'élément
pointé pour progresser dans ce tableau ?
Ca, c'est un pointeur très habile !
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