Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1280 connectés 

 


Dernière réponse
Sujet : [C] : Une fonction peut elle renvoyer un tableau ??
BifaceMcLeOD Verdoux> Yep, tu as (encore) raison, le "vecteur::" était de trop !
 
Je sens que je vais arrêter de répondre aux questions C++, moi, ça fait trop longtemps que je n'en ai pas fait.
 
z51> Rien ne dit que les fonctions que j'ai écrites sont ou non sont pas inline (puisqu'il manque la définition de la classe elle-même). Mais ce qu'elles sont censées optimiser, ces fonctions, c'est la consommation mémoire (le += ne consomme rien). Et puis il n'est pas évident que l'appel de fonction que tu souhaite économiser soit vraiment pénalisant. Comme l'a souligné Verdoux au sujet des matrices, il y a d'autres "optimisations" beaucoup plus efficaces en modifiant carrément l'interface et les algorithmes.

Votre réponse
Nom d'utilisateur    Pour poster, vous devez être inscrit sur ce forum .... si ce n'est pas le cas, cliquez ici !
Le ton de votre message                        
                       
Votre réponse


[b][i][u][strike][spoiler][fixed][cpp][url][email][img][*]   
 
   [quote]
 

Options

 
Vous avez perdu votre mot de passe ?


Vue Rapide de la discussion
BifaceMcLeOD Verdoux> Yep, tu as (encore) raison, le "vecteur::" était de trop !
 
Je sens que je vais arrêter de répondre aux questions C++, moi, ça fait trop longtemps que je n'en ai pas fait.
 
z51> Rien ne dit que les fonctions que j'ai écrites sont ou non sont pas inline (puisqu'il manque la définition de la classe elle-même). Mais ce qu'elles sont censées optimiser, ces fonctions, c'est la consommation mémoire (le += ne consomme rien). Et puis il n'est pas évident que l'appel de fonction que tu souhaite économiser soit vraiment pénalisant. Comme l'a souligné Verdoux au sujet des matrices, il y a d'autres "optimisations" beaucoup plus efficaces en modifiant carrément l'interface et les algorithmes.
verdoux Ouais c'est pas très optimal.
Mais pour faire des truc assez efficace, il faut pas mal réfléchir.
Un exemple de librairie optimisée:
http://www.oonumerics.org/blitz/
 
Ca permet d'écrire des trucs du genre:
Array<float,2> A(64,64), B(64,64);   // 2 matrices 64x64
Range I(1,62), J(1,62); // on définit 2 indices avec leurs plages.
 
// et on peut calculer par exemple:
A(I,J) = (B(I,J) + B(I+1,J) + B(I-1,J)  
                 + B(I,J+1) + B(I,J-1)) / 5;
 
Cette dernière écriture est vraiment très proche de ce qu'on écrit mathématiquement.  
Et l'évaluation est très efficace car on ne fait que 2 boucles (l'une sur I, l'autre sur J) alors que si on prend des opérateurs définis "simplement", le calcul de A+B+C+D+E est évalué en A + (B + (C + (D + E))) soit 4x2 boucles.

 

--Message édité par Verdoux--

z51 Arrête moi si je me trompe, mais ça n'optimise en rien l'opérateur +() d'appeler +=()
Ca le ralentit même si tes fonctions ne sont pas inline.
verdoux Oui mais si il est friend, il est en dehors de la classe. Donc il s'appelle pas vecteur::operator+ mais simplement operator+ :)
BifaceMcLeOD

Verdoux a écrit a écrit :

Euh là ça va pas le faire.
Déja le premier opérateur doit retourner *this.
 
Ensuite le second définit un opérateur ternaire et en plus retourne une référence sur un temporaire.




Oups! J'ai oublié une étoile dans mon premier return... :D (preuve que j'ai tapé ce code sans même le compiler !)
 
Par contre, pour l'opérateur ternaire, je ne suis pas d'accord : en général, quand on écrit le proto tel que je l'ai écrit (sauf qu'il ne doit pas renvoyer pas de référence, là, je te donne raison), c'est que l'opérateur est friend ! Mais bon, on peut aussi le déclarer non-friend et ne mettre qu'un seul paramètre... ;)
 
Bon, je vais quand même corriger ce code tout plein d'erreurs : :D
 
vecteur& vecteur::operator+=(vecteur const& a)
{
    this->i += a.i;
    this->j += a.j;
    this->k += a.k;
 
    return *this;
}
 
vecteur vecteur::operator+(vecteur const& a) const
{
    vecteur  result(*this);
 
    result += b;
    return result;
}

Roswell_ C'est bon merci les gars j'ai capté :jap:
verdoux Euh là ça va pas le faire.
Déja le premier opérateur doit retourner *this.
 
Ensuite le second définit un opérateur ternaire et en plus retourne une référence sur un temporaire.
BifaceMcLeOD z51> Je me demande si operator+() ne doit pas renvoyer une référence...
 
Sinon, si vous voulez faire dans l'optimisé dans vos redéfinitions d'opérateurs, je vous conseille d'implémenter operator+=() d'abord, puis appeler operator+=() dans l'implémentation d'operator+(). Et pas le contraire (i.e. appeler operator+() dans l'implémentation d'operator+=()). Ainsi :
 
vecteur& vecteur::operator+=(vecteur const& a)
{
    this->i += a.i;
    this->j += a.j;
    this->k += a.k;
 
    return this;
}
 
vecteur& vecteur::operator+(vecteur const& a, vecteur const b)
{
    vecteur  result(a);
 
    result += b;
    return result;
}
 
Bien sûr il ne faut avoir oublié le constructeur par recopie :
vecteur::vecteur(vecteur const& a)
    : i(a.i), j(a.j), k(a.k)
{
}
 
Avantage: operator+() ne change pas, mais operator+=() ne requiert pas de mémoire supplémentaire (=> plus optimisé).
z51 En reprendrenant l'exemple de Viper :
 
vecteur operator+(vecteur const &A, vecteur const &B)  
{  
vecteur tmp;  
tmp.i = A.i + B.i;  
tmp.j = A.j + B.j;  
tmp.k = A.k + B.K;  
 
return tmp;  
}  
 
Et après tu peux directement écrire : A = B + C
où A, B et C sont trois vecteurs.
 
Sur des structures plus importantes (les matrices par ex) la surcharge est assez pénalisante, mais c'est tellement plus lisible ...
Roswell_ Allez un ch'tit exemple pour ma culture :p
BifaceMcLeOD la viper> C'est le bon sens même ! :sol:
la viper surtout pour une fonction qui n'a pour vocation que d'additionner deux structures de 2 entiers !!!!!!
 
Faut pas se prendre la tete !!!  
 
toujours aller au plus simple et ou plus facile a coder  
 
car :
- moins de ligne de code
- moins de bourrage de tete
 
et donc moins de BUG !
BifaceMcLeOD La surcharge d'opérateur, c'est très pratique, mais ça peut finir par être dangereux, car on finit par ne plus savoir ce que l'on fait.
Croyez-en mon expérience... pour avoir vu des programmeurs redéfinir les opérateurs new et delete. Là, ça commence à devenir plus intéressant d'acheter des actions dans les fabricants d'aspirine...  ;)
Roswell_ xilebo>
Tu pourrais me mettre un exemple, je sais pas faire:)
xilebo tu devrais essayer le C++ , car la surcharge d'operateur ( ici l'operateur + , * et = ) c'est super pratique. En effet dans le code c'est mieux de mettre C = A + B ou C = A * B plutot que C = somme(A,B) ou C = produit(A,B).
la viper vous vous prenez vraiment le choux les mecs !!! effectivement renvoyer une structure de hum ... 3*2 octets .. soit 6 octets au lieu d'un pointeur de 4 octets ca vaut vachement le coup !!! :eek2:  
 
parfois, il faut faire abstration de tous ces petits probleme pour aller au plus simple .. j'vous promet que meme un 286 ne vera pas la difference.
wouatouwouatou :)
Toxin Ou faire un truc du genre
 
int* retournetableau()  
{  
static int tab[5] = {0};  
return tab;  
}
wouatouwouatou c bien vrai... vaut mieu eviter de prendre cette habitude au depart... car une structure est tellement variable!!!
Kom je lai dit plus haut.. je prefere la soluce de damned.
Car ta fonction n'est pas sensée toucher koi ke ce  soi a la memoire... au nivo alloc
BifaceMcLeOD oh_damned> Oui, mais la structure est retournée, donc une copie en sera faite avant, et c'est cette copie qui sera utilisée par le main. Ce n'est pas comme si on retournait un pointeur sur cette structure locale...
 
Le seul inconvénient à retourner une structure, c'est que ce n'est pas d'une efficacité à toute épreuve. Mais quand on débute en programmation, c'est la dernière chose à laquelle penser ! :D
oh_damned la viper a écrit :
 
>>>vecteur somme(vecteur A,vecteur B)  
>>>{  
>>>  vecteur tmp;:hot:  
>>>  tmp.i = A.i + B.i;  
>>>  tmp.j = A.j + B.j;  
>>>  tmp.k = A.k + B.K;  
>>>  return tmp;:gun:
>>>}  
 
en C, à moins de déclarer une variable static, elle est détruite à la fin du bloc où elle est déclarée, donc ici pour utiliser le résultat dans main ça risque d'être catastrophique
 
personnellement je passerais en paramètres les adresses des 2 tableaux à sommer + l'adresse du tableau résultat, à alouer évidemment avant l'appel
Pschitt Merci à toi grande Viper
 
Même pas le temps de finir de tester une fonction que m'a envoiée BifaceMcLeOD sur un autre sujet que voila une réponse à cette question (Qui + est Avé le code)
 
C'est vraiment le pied  
 
Merci beaucoup
la viper moi je ferais ca !
 
struct vecteur
{
int i,j,k;
}
 
vecteur somme(vecteur A, vecteur B);
vecteur produit(vecteur A,vecteur B);
 
void main(void)
{
vecteur A,B,C,D;
C = somme(A,B);
D = produit(A,B);
}
 
vecteur somme(vecteur A,vecteur B)
{
vecteur tmp;
tmp.i = A.i + B.i;
tmp.j = A.j + B.j;
tmp.k = A.k + B.K;
 
return tmp;
}
 
idem pour produit
 
ici pas besoin de tableau et de pointeur !!
Pschitt Je ne pensais pas provoquer un tel débat ??
J'm'aperçois qu'il y a des C(iens) avertis dans ce forum -> Tant mieux parceque pour ma part c'est le démarrage et j'ai encore du chemin à faire mais j'aime bien ça.
 
Le but de ma question était de savoir si je pouvais envoyer 2 vecteurs à une fct et de lui demander m'en rendre la somme ou le produit.
Dailleur cette adresse en retour, je peux l'affecter à un autre tableau directement(:ouch: ) ou pluôt lui faire pointer un int *.    
 
Merci à vous tous pour votre aide
la viper effectivement j'ai pas trop reflechi là !!!
toutes mes escuses ..
int* EnDynamique(int valeur)
{
int* ptr = (int)malloc(valeur*sizeof(int));
return ptr;
}
 
Le seul reproche qui est a faire ici est qu'on passe par deux pointeur. Et que dans ce cas là, on aura p etre un probleme d'adresse a remettre à jour si on agrandit la zone de memoire alouée à ptr.
 
bref, ct juste pour montrer que ct possible et que d'ailleur il est recommandé de faire des passages d'adresse plutot que de variable! vous confirmez ??
verdoux Dans ce cas, il faut bien se souvenir qu'on a alloué de la mémoire avec cette fonction et penser à la libérer sinon ça fuit.
xilebo Je ne comprends pas pourquoi c'est crade d'allouer dynamiquement à l'intérieur de la fonction ? Pour moi ca revient au même .
wouatouwouatou le mieux c de faire faire passer un tableau en parametre...
Comme ca ta fonction est dechargée de tout ce ki est gestion de memoire... et elle peut donc se concentrer sur son but...
Malkav C'est clair la viper ->
ne retourne jamais l'adresse d'une var locale !
Soit tu passes le tableau en paramètre de ta fonction, soit tu fais de l'allocation dynamique à l'intérieur (mais c'est crade)
verdoux Oui mais là c'est très dangereux, tu retourne l'adresse d'une variable locale !
la viper ex :
 
int* retournetableau()
{
int tab[5] = {0};
return tab;
}
la fonction retourne l'adresse du pointeur tab soit l'adresse du premier element du tableau soit l'adresse de tab[0].
wouatouwouatou euh... retourner un tableau c retourner une adresse :D
darkoli surtout son adresse ...
BifaceMcLeOD En général, oui, mais en C, un tableau est déjà un pointeur, donc il n'y a même aucun risque d'exploser la pile...
z51 oui c'est tout à fait possible, mais en pratique tu n'as pas du tout intérêt à surcharger la pile, il vaut 1000 fois mieux passer par un pointeur ou une référence.

 

--Message édité par z51--

Pschitt Voir son adresse ?

Copyright © 1997-2025 Groupe LDLC (Signaler un contenu illicite / Données personnelles)