OVH Cloud OVH Cloud

[BCB6 /STL] Violation d'acces dans un classe et sa collection

39 réponses
Avatar
Olivier
Bonjoiur
je fait une collection d'article (std::vector<TArticle *> _pCoArt;)

le probleme quand je supprime un article
ou quand il est le dernier et que je veuille en ajouter un
autre j'ai une violation d'acces

voici le code de la suppression :


bool __fastcall TCoArticles::DeleteArticle(TArticle& Art)
{//@CODE_347

bool bRes=false;

if(int max =Count()>0){

int i=0;

if(SearchArticle(Art,i)){

TArticle *_pArt=_pCoArt.at(i);

if(i==max || max==1){
_pCoArt.push_back();
}else{
_pCoArt.erase(&_pArt);
}
delete _pArt;
bRes=true;
}
}else{
TMyError Err(7,"Collection d'article est vide");
throw Err;
}
return bRes;
}//@CODE_347


le code SearchArticle

bool __fastcall TCoArticles::SearchArticle(TArticle& Art, int& i)
{//@CODE_357
bool bRes=false;
std::vector<TArticle*>::iterator i_end =_pCoArt.end();
int j=0;

for(std::vector<TArticle*>::iterator it=_pCoArt.begin();it!=i_end;++it){

if((*it)->NomArt==Art.NomArt && (*it)->Description==Art.Description &&
(*it)->Categorie==Art.Categorie && (*it)->Prix==Art.Prix){

i=j;
bRes=true;
break;

}
j++;
}

return bRes;
}//@CODE_357

ou est mon erreur ?
que dois je faire ?

merci de vos reponses....
--
Cordialement ,
Sarda Olivier

Site Web:
http://membres.lycos.fr/osarda

10 réponses

1 2 3 4
Avatar
Gabriel Dos Reis
writes:

[...]

| > Oui : comme le compilateur (sur sa machine) est assez idiot pour ne
| > pas mettre une structure qui contient uniquement un pointeur dans un
| > registre, il préfère que nous renoncions à un type distinct de T*.
|
| C'est bête, mais j'avais oublié cette histoire-là. Si ça te rassure, g++
| n'est pas le seul à être aussi idiot, loin de là. (Ce qui est curieux,
| parce qu'il me semble d'avoir lu des propos de Strustrup sur l'intérêt
| de passer des petites classes par des régistres il y a environ 12/13
| ans, sinon plus. Je me démande s'il n'en a pas parlé dans la première
| version de TC++PL. Ce n'est donc pas vraiment une idée nouvelle.)

Oui. Le problème fondamental tel je le perçois est que l'ABI d'une
machine est souvent défini par des gens plutôt de la culture C, qui
n'ont pas beaucoup considéré qu'une structure ne veut pas forcément
dire gros (et qu'en conséquence, une structure peut très bien tenir
dans un registre). Bien sûr la situation évolue peu à peu (par exemple
PowerPC ne demande pas qu'une structure passe systématiquement dans le
tas). Mais nombre de machines encore populaires (genre SPARC, x86) ont
une attitude assez abracadantesque envers les structs.
Bien sûr, il appartient aussi aux constructeurs de compilateurs de
bien distinguer le fait que C++ dispose d'au moins deux conventions
d'appel (C++ et C) et ils ne sont pas obligés de dire que la
convention d'appel C++ est la même que celle de C. Globalement, c'est
une question d'avoir compris à quoi sert un type.

L'intérêt de passer des petites classes dans des registres m'a
toujours paru évident, peut-être parce que je ne suis pas passé par la
case C avant d'arriver à C++.

[...]

| > Comme souvent, le problème est ailleurs et la solution effective est
| > d'enseigner au compilateur à inliner effectivement et virer les
| > junks. Car les opérations incriminées sont essentiellement
|
| > 1) lire la valeur brute du pointeur
| > 2) comparer les valeurs brutes de deux pointeurs.
|
| J'aurais pensé que le passage des paramètres et le retour des fonctions
| soient où la différence se fait le plus sentir.

La personne qui a fait la demande a donné

sort(v.begin(), v.end())

comme exemple, où v est un std::vector<T>.

| Si j'ai quelque chose
| comme :
|
| struct S { T* ptr } s1, s2 ;
|
| s1.ptr == s2.ptr ;
|
| avec tout visible au compilateur (grace aux fonctions inline), je me
| poserais vraiment des questions si le compilateur générait un code
| différent de ce qu'il aurait fait avec des pointeurs bruts.

Ce dont je parle est ceci

struct vector_iterator {
T* ptr;
};

inline bool
operator==(vector_iterator p, vector_iterator q)
{ return p.ptr == q.ptr; }


Le compilateur devrait faire son boulot et comprendre que p == q, c'est
p.ptr == q.ptr.

Mais tant qu'une partie des gens de middle end ou back end
maintiendront que le compilateur sait mieux que le programmeur et que
inline doit être traité comme register (i.e. sans signification) sans
tenir compte des usages et de la sémantique du langage, alors
même qu'on ne dispose pas de la technologie pour prétendre cela, on en
viendra à l'hérésie rapportée plus tôt.

| Le problème des paramètres et des retours de fonctions est un peu plus
| subtile, parce qu'il vaut mieux que le compilateur fasse la même chose
| au point de l'appel et dans la fonction (qui sont souvent dans deux
| unités de compilations différentes, compilées avec des options
| d'optimisation différentes). Passer une classe comme S, ci-dessus,
| pourrait poser des problèmes si on avait besoin ou d'un côté ou de
| l'autre. Et pour appeler une fonction membre, il en faut l'adresse.

Oui, mais cela ne démontre pas qu'on doive toujours passer par le tas.
La valeur de retour d'une fonction de type class est une rvalue, donc
on ne peut pas en prendre l'adresse. Pour un paramètre, on ne peut pas
en prendre l'adresse dans l'appelante, et dans l'appellée le paramètre
est une variable, donc a une adresse définie, on la traite comme les
autres paramètres.

| > Actuellement, dès que le compilateur voir "struct" il dit "Oh là,
| > celui là ne veut pas d'efficacité, allez hop dans le tas" sans
| > chercher à savoir si le "struct" en question sert just à distinguer
| > une valeur des autres et que cette distinction est purement
| > compile-time.
|
| > On voit que le compilateur est écrit essentiellement par des
| > programmeurs C.
|
| Juste curieux, mais par « est écrit », est-ce que tu veux dire « a été
| écrit », ou « s'écrit actuellement » ?

En fait je voulais dire les deux.

-- Gaby
Avatar
Olivier
Tout d'abord merci de vos precieux conseil
je suis un autodidacte qui souffre avec la STL dur dur

_pCoArt est devenu _pArtList

voici le nouveau code dans la classe collection TCoArticle

std::vector<TArticle*>::const_iterator TCoArticles::SearchArticle(TArticle &
Art)
{
return std::find(_pArtList.begin(),_pArtList.end(),&Art);
}


La suppression :

bool __fastcall TCoArticles::DeleteArticle(TArticle& Art)}
{
bool bResúlse;
std::vector<TArticle*>::const_iterator i;
i= SearchArticle(Art);

if(i){
_pArtList.erase( _pArtList.begin()+ (i -_pArtList.end())) ;
delete *i; // violation pourquoi ??? que le mette avant ou apres le errse
}else{

bResúlse;
}

}
merci encore a tous de votre gentillesse j'apprend beauocup avec vous sur ce
forum .
Avatar
Olivier
Bonjour
je precise j'ai 2 classes une la classe TArticle et l'autre sa collection
TCoArticles
dnas 'linterface graphique j'ai sur sur le contructeur deux ponteurs sur
chacunes des classes
je fais 2 news.

Projet fait sur Borland C++Builder 6 et Windows 98 code guard active
option de complition standard faut il changer une option ?
autre precison outil UML utilise ClassBuilder 2.4 gratuit generation du
squellette des classes uniquement
file://---------------------------------------------------------------------
----------------------------------------------------------------
bool __fastcall TCoArticles::DeleteArticle(TArticle& Art)
{//@CODE_347

bool bResúlse;

if (Count()>0){ // size()
std::vector<TArticle*>::const_iterator it=NULL;

it= SearchArticle(Art);

// if(it!=_pArtList.end()){ // ce test ne marche pas il le saute
// par contre si je fait

if(it){ // ce test passe mais sur delete *it j'ai une violation
d'acces
_pArtList.erase( _pArtList.begin()+ (it -_pArtList.end())) ;
delete *it;
bRes=true;
}

}else{
TMyError Err(7,"Collection d'article est vide");
throw Err;
}
return bRes;
}
file://---------------------------------------------------------------------
----------------------------------------------------------------
std::vector<TArticle*>::const_iterator TCoArticles::SearchArticle(const
TArticle &Art)
{
return std::find(_pArtList.begin(),_pArtList.end(),&Art);
}
file://---------------------------------------------------------------------
----------------------------------------------------------------------

Autre question ai je les bon header ?
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>

file://---------------------------------------------------------------------
----------------------------------------------------------------
Si je fait _pArtList.erase(it)

bcb=>
[C++ Erreur] CoArticles.cpp(123): E2285 Impossible de trouver une
correspondance pour '_STL::vector<TArticle *,_STL::allocator<TArticle *>
::erase(TArticle * const *)'


Le selecteur de fonction attend pArtList.erase(TArticle **__position)
ou pArtList.erase(TArticle
**__first,TArticle **__Last)

ou est l'erreur ?


merci encore de vos reponse et aide

Avatar
Olivier
Bonjour
je precise j'ai 2 classes une la classe TArticle et l'autre sa collection
TCoArticles
dnas 'linterface graphique j'ai sur sur le contructeur deux ponteurs sur
chacunes des classes
je fais 2 news.

Projet fait sur Borland C++Builder 6 et Windows 98 code guard active
option de complition standard faut il changer une option ?
autre precison outil UML utilise ClassBuilder 2.4 gratuit generation du
squellette des classes uniquement
file://---------------------------------------------------------------------
----------------------------------------------------------------
bool __fastcall TCoArticles::DeleteArticle(TArticle& Art)
{//@CODE_347

bool bResúlse;

if (Count()>0){ // size()
std::vector<TArticle*>::const_iterator it=NULL;

it= SearchArticle(Art);

// if(it!=_pArtList.end()){ // ce test ne marche pas il le saute
// par contre si je fait

if(it){ // ce test passe mais sur delete *it j'ai une violation
d'acces
_pArtList.erase( _pArtList.begin()+ (it -_pArtList.end())) ;
delete *it;
bRes=true;
}

}else{
TMyError Err(7,"Collection d'article est vide");
throw Err;
}
return bRes;
}
file://---------------------------------------------------------------------
----------------------------------------------------------------
std::vector<TArticle*>::const_iterator TCoArticles::SearchArticle(const
TArticle &Art)
{
return std::find(_pArtList.begin(),_pArtList.end(),&Art);
}
file://---------------------------------------------------------------------
----------------------------------------------------------------------

Autre question ai je les bon header ?
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>

file://---------------------------------------------------------------------
----------------------------------------------------------------
Si je fait _pArtList.erase(it)

bcb=>
[C++ Erreur] CoArticles.cpp(123): E2285 Impossible de trouver une
correspondance pour '_STL::vector<TArticle *,_STL::allocator<TArticle *>
::erase(TArticle * const *)'


Le selecteur de fonction attend pArtList.erase(TArticle **__position)
ou pArtList.erase(TArticle
**__first,TArticle **__Last)

ou est l'erreur ?


merci encore de vos reponse et aide

Avatar
Christophe Lephay
"Olivier" a écrit dans le message de
news:3f2cddaf$0$27407$
bool bResúlse;

if (Count()>0){ // size()
std::vector<TArticle*>::const_iterator it=NULL;

it= SearchArticle(Art);

// if(it!=_pArtList.end()){ // ce test ne marche pas il le saute


Qu'est-ce que ça veut dire, il le saute ?

// par contre si je fait

if(it){ // ce test passe mais sur delete *it j'ai une violation
d'acces
_pArtList.erase( _pArtList.begin()+ (it -_pArtList.end())) ;
delete *it;
bRes=true;
}

}else{
TMyError Err(7,"Collection d'article est vide");
throw Err;
}
return bRes;
}

file://---------------------------------------------------------------------

----------------------------------------------------------------
std::vector<TArticle*>::const_iterator TCoArticles::SearchArticle(const
TArticle &Art)
{
return std::find(_pArtList.begin(),_pArtList.end(),&Art);
}

file://---------------------------------------------------------------------

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

Si je fait _pArtList.erase(it)

bcb=>
[C++ Erreur] CoArticles.cpp(123): E2285 Impossible de trouver une
correspondance pour '_STL::vector<TArticle *,_STL::allocator<TArticle *>
::erase(TArticle * const *)'


Le selecteur de fonction attend pArtList.erase(TArticle **__position)
ou pArtList.erase(TArticle
**__first,TArticle **__Last)

ou est l'erreur ?


L'erreur c'est que le type de it et de ta fonction SearchArticle est un
const_iterator. C'est normal que tu puisses pas t'en servir pour supprimer
des éléments dans ton vector...

Chris


merci encore de vos reponse et aide
















Avatar
Luc Hermitte
Salut

"Olivier" wrote in
news:3f2cddaf$0$27407$:

Projet fait sur Borland C++Builder 6 et Windows 98 code guard active
option de complition standard faut il changer une option ?
autre precison outil UML utilise ClassBuilder 2.4 gratuit generation
du squellette des classes uniquement


Il a fait des progrès cet outil ? Dans le passé, son mainteneur ne voulait
pas supporter la STL et imposait à la place ses propres conteneurs.

bool TCoArticles::DeleteArticle(TArticle& Art)


bool TCoArticles::DeleteArticle(const TArticle& Art)


{
bool bResúlse;

if (Count()>0){ // size()
std::vector<TArticle*>::const_iterator it=NULL;
it= SearchArticle(Art);


std::vector<TArticle*>::iterator it std::find_if(_pArtList.begin(),_pArtList.end(),
std::bind2nd( IsEqualPointedTo<TArticle>(), &Art));


// if(it!=_pArtList.end()){ // ce test ne marche pas il le
saute // par contre si je fait


Si il le saute, ça veut dire qu'il n'a rien trouvé.

D'autant que c'est le seul et unique test valide à faire. "if (it)" n'a pas
de sens. it est un iterateur, pas un pointeur. Déjà l'initialiser à NULL
(ou même 0) n'a pas de sens. [bon d'accord, ici il est implémenté 99% du
temps comme un pointeur ; mais ce servir de cet aspect d'implémentation est
sémantiquement faux]

if(it){ // ce test passe mais sur delete *it j'ai une violation
d'acces
_pArtList.erase( _pArtList.begin()+ (it -_pArtList.end())) ;


_pArtList.erase(it); // tout simplement

delete *it;
bRes=true;
}
}


Le problème est que ton Article n'a pas été trouvé car tu faisais une
recherche sur des pointeurs d'articles et pas des articles. Cf. juste après
pour ce qui te manque.


file://----------------------------------------------------------------
-----
----------------------------------------------------------------------

Autre question ai je les bon header ?
#include <vector>
#include <iterator>
#include <algorithm>
#include <functional>


A priori, tu n'as pas besoin ici de <iterator>; mais bien de <functional>
car il te faut rajouter ce qui suit pour pouvoir comparer des articles
ensembles (et pas des adresses d'articles) :

template< typename T >
struct IsEqualPointedTo
: std::binary_function<const T*, const T*, bool>
// James, tu avais oublié l'héritage avec binary_function ;)
{
bool operator()( T const* lhs, T const* rhs ) const {
return *lhs == *rhs ;
}
} ;

bool TArticle::operator==(const TArticle &a) const {
return Categorie_==a.Categorie_ && Description_==a.Description_
&& NomArt_==a.NomArt_;
// Rem: j'ai ignoré le prix ici
}



file://----------------------------------------------------------------
----- ----------------------------------------------------------------
Si je fait _pArtList.erase(it)

bcb=>
[C++ Erreur] CoArticles.cpp(123): E2285 Impossible de trouver une
correspondance pour '_STL::vector<TArticle *,_STL::allocator<TArticle
*>
::erase(TArticle * const *)'


Le selecteur de fonction attend pArtList.erase(TArticle **__position)
ou pArtList.erase(TArticle
**__first,TArticle **__Last)

ou est l'erreur ?


Enlève le const_ de const_iterator

merci encore de vos reponse et aide



Ca devrait mieux aller maintenant. [Au pire, j'ai écrit un petit code test
que je peux t'envoyer]

--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>


Avatar
Olivier
Christophe Lephay a écrit dans le message :
bgir65$uf$
"Olivier" a écrit dans le message de
news:3f2cddaf$0$27407$
bool bResúlse;

if (Count()>0){ // size()
std::vector<TArticle*>::const_iterator it=NULL;

it= SearchArticle(Art);

// if(it!=_pArtList.end()){ // ce test ne marche pas il le saute


Qu'est-ce que ça veut dire, il le saute ?

en mode pas a pas le compliateur n'execute pas le bloc d'instruction

en dessous et la fonction retourne false



// par contre si je fait

if(it){ // ce test passe mais sur delete *it j'ai une violation
d'acces
_pArtList.erase( _pArtList.begin()+ (it -_pArtList.end())) ;
delete *it;
bRes=true;
}

}else{
TMyError Err(7,"Collection d'article est vide");
throw Err;
}
return bRes;
}



file://---------------------------------------------------------------------

----------------------------------------------------------------
std::vector<TArticle*>::const_iterator TCoArticles::SearchArticle(const
TArticle &Art)
{
return std::find(_pArtList.begin(),_pArtList.end(),&Art);
}



file://---------------------------------------------------------------------

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

Si je fait _pArtList.erase(it)

bcb=>
[C++ Erreur] CoArticles.cpp(123): E2285 Impossible de trouver une
correspondance pour '_STL::vector<TArticle *,_STL::allocator<TArticle *>
::erase(TArticle * const *)'


Le selecteur de fonction attend pArtList.erase(TArticle **__position)
ou pArtList.erase(TArticle
**__first,TArticle **__Last)

ou est l'erreur ?


L'erreur c'est que le type de it et de ta fonction SearchArticle est un
const_iterator. C'est normal que tu puisses pas t'en servir pour supprimer
des éléments dans ton vector...

Chris


merci encore de vos reponse et aide




















Avatar
kanze
Gabriel Dos Reis wrote in message
news:...
writes:

[...]

| > Oui : comme le compilateur (sur sa machine) est assez idiot pour
| > ne pas mettre une structure qui contient uniquement un pointeur
| > dans un registre, il préfère que nous renoncions à un type
| > distinct de T*.

| C'est bête, mais j'avais oublié cette histoire-là. Si ça te rassure,
| g++ n'est pas le seul à être aussi idiot, loin de là. (Ce qui est
| curieux, parce qu'il me semble d'avoir lu des propos de Strustrup
| sur l'intérêt de passer des petites classes par des régistres il y a
| environ 12/13 ans, sinon plus. Je me démande s'il n'en a pas parlé
| dans la première version de TC++PL. Ce n'est donc pas vraiment une
| idée nouvelle.)

Oui. Le problème fondamental tel je le perçois est que l'ABI d'une
machine est souvent défini par des gens plutôt de la culture C, qui
n'ont pas beaucoup considéré qu'une structure ne veut pas forcément
dire gros (et qu'en conséquence, une structure peut très bien tenir
dans un registre).


En plus de la culture C, il y a aussi l'idée, je crois que « one size
fits all ». Il y a bien des structures qu'on peut pas passer par des
régistres ; donc, on ne pas pas les structures par les régistres. Et ce
n'est pas forcement un problème de taille. Considérons une classe qui
utilise l'idiome de compilation firewall. Avec un constructeur de copie
qui n'est pas trivial, et qui n'est pas en ligne. Alors, pour faire la
copie, le compilateur est obligé à passer l'adresse de l'objet au
constructeur de copie. Du coup, on ne peut pas mettre l'objet dans un
régistre.

Certes, ce n'est pas grave pour de tels objets. Le temps de faire la
copie dépasse largement le temps de passage du paramètre par mémoire.
Mais du coup, la taille de l'objet ne peut pas être le critère unique
pour le passage par régistre. Il faut au minimum que les constructeurs
(et destructeurs ?) qu'on appelle soit en ligne. Et j'ai l'impression
que faire passer des paramètres différemment simplement parce que le
compilateur dispose de davantage d'informations est une voie qui fait un
peu peur aux auteurs du compilateur.

Bien sûr la situation évolue peu à peu (par exemple PowerPC ne demande
pas qu'une structure passe systématiquement dans le tas). Mais nombre
de machines encore populaires (genre SPARC, x86) ont une attitude
assez abracadantesque envers les structs. Bien sûr, il appartient
aussi aux constructeurs de compilateurs de bien distinguer le fait que
C++ dispose d'au moins deux conventions d'appel (C++ et C) et ils ne
sont pas obligés de dire que la convention d'appel C++ est la même que
celle de C. Globalement, c'est une question d'avoir compris à quoi
sert un type.

L'intérêt de passer des petites classes dans des registres m'a
toujours paru évident, peut-être parce que je ne suis pas passé par la
case C avant d'arriver à C++.


Ça m'a toujours paru évident à moi aussi, et j'ai passé par la case C.
Je suis prèsque sûr que je l'ai lu aussi de Stroustrup (qui a aussi
passé par la case C). Ça fait du coup trois personnes au moins qui ont
eu l'idée, et qui en trouve de l'intérêt ; je ne crois donc pas qu'elle
soit quelque chose d'extraordinaire. Je crois plutôt que, comme tu dis,
l'intérêt est évident.

[...]

| > Comme souvent, le problème est ailleurs et la solution effective
| > est d'enseigner au compilateur à inliner effectivement et virer
| > les junks. Car les opérations incriminées sont essentiellement

| > 1) lire la valeur brute du pointeur
| > 2) comparer les valeurs brutes de deux pointeurs.

| J'aurais pensé que le passage des paramètres et le retour des
| fonctions soient où la différence se fait le plus sentir.

La personne qui a fait la demande a donné

sort(v.begin(), v.end())

comme exemple, où v est un std::vector<T>.


Intéressant. Parce que dans le cas des templates (au moins avec g++, et
la plupart des autres compilateurs aussi), le compilateur a accès à
l'implémentation de la fonction. Ici, absolument rien n'empèche au
compilateur de passer la classe par un régistre -- ne des histoires de
l'API externe, ni des questions de ne pas savoir ce qui se passe dans le
constructeur, ni des questions (éventuelles) à savoir ce qui se passe
dans la fonction appelée. (A priori, je ne crois pas que cette dernière
question pose un problème, mais n'ayant pas réelement implémenté quoique
ce soit, il vaut mieux que je sois prudent.)

| Si j'ai quelque chose
| comme :

| struct S { T* ptr } s1, s2 ;

| s1.ptr == s2.ptr ;

| avec tout visible au compilateur (grace aux fonctions inline), je me
| poserais vraiment des questions si le compilateur générait un code
| différent de ce qu'il aurait fait avec des pointeurs bruts.

Ce dont je parle est ceci

struct vector_iterator {
T* ptr;
};

inline bool
operator==(vector_iterator p, vector_iterator q)
{ return p.ptr == q.ptr; }

Le compilateur devrait faire son boulot et comprendre que p == q,
c'est p.ptr == q.ptr.


En dehors du nom de la classe, est-ce que j'ai dit quelque chose d'autre ?

Mais tant qu'une partie des gens de middle end ou back end
maintiendront que le compilateur sait mieux que le programmeur et que
inline doit être traité comme register (i.e. sans signification) sans
tenir compte des usages et de la sémantique du langage, alors même
qu'on ne dispose pas de la technologie pour prétendre cela, on en
viendra à l'hérésie rapportée plus tôt.


Mais ce n'est pas le cas de g++, non ? Il met bien les fonctions inline,
quand on démande de l'optimisation. Et une fois que la fonction
ci-dessus inline, l'optimisateur de peep-hole doit suffire pour faire la
reste.

C'était au moins ce qui se passait avec le compilateur Zortech, il y a
prèsque quinze ans. Pas avec des templates, évidemment ; il ne
supportait pas les templates. Mais si tu écrivais quelque chose comme
ci-dessus, ET tu démandais l'optimisation, il réduisait bien le code à
une simple comparaisons de pointeurs.

Ceci dit, il le faisait bien dans la phase de peep-hole optimization.
(Je m'excuse de l'anglais, mais dans ce cas-ci, tout ce que j'ai lu est
en anglais, et je n'ai travaillé sur des compilateurs qu'en Allemagne.)
C-à-d sur le code machine, après la génération du code. Et donc, d'une
façon qui dépendant de la machine. Je peux imaginer que ce genre
d'optimisation pose des problèmes pour un compilateur portable, comme
g++. (Mais alors, quelle est l'excuse de Sun CC, qui ne le fait pas non
plus.)

| Le problème des paramètres et des retours de fonctions est un peu
| plus subtile, parce qu'il vaut mieux que le compilateur fasse la
| même chose au point de l'appel et dans la fonction (qui sont souvent
| dans deux unités de compilations différentes, compilées avec des
| options d'optimisation différentes). Passer une classe comme S,
| ci-dessus, pourrait poser des problèmes si on avait besoin ou d'un
| côté ou de l'autre. Et pour appeler une fonction membre, il en faut
| l'adresse.

Oui, mais cela ne démontre pas qu'on doive toujours passer par le tas.


Quand tu dis « tas », tu veux dire « pile », non ? Au moins que je me
trompe (mais ça ne sera pas la première fois), tas, c'est le « heap »,
où il y a de la mémoire allouée dynamiquement, et pile, c'est le
« stack », un mémoire à accès premier entré, dernier sorti.

La valeur de retour d'une fonction de type class est une rvalue, donc
on ne peut pas en prendre l'adresse. Pour un paramètre, on ne peut pas
en prendre l'adresse dans l'appelante, et dans l'appellée le paramètre
est une variable, donc a une adresse définie, on la traite comme les
autres paramètres.


La distinction rvalue/lvalue s'éstompe avec des classes où le
constructeur n'est pas trivial. Si, par exemple, le constructeur de
copie met l'adresse quelque part où la fonction appelée peut la voir,
des modifications à travers cette adresse doivent se répercuter sur le
paramètre.

Ceci dit, si le constructeur de copie est en ligne, le compilateur doit
bien pouvoir savoir que l'adresse ne s'en échappe pas.

Je ne vois qu'un problème. Problème que je crois n'apparaît pas dans le
code réel, mais que la norme permet. Si on fait dépendre la façon que le
paramètre est passé de ce que le constructeur de copie soit inline ou
non, il y a une risque qu'il soit inline où la fonction est appelée, et
non inline où la fonction est définie. Or, si à l'appel, on passe le
paramètre par un régistre, mais dans la fonction, on s'attend à le
trouver sur la pile, il va y avoir un petit problème.

Considère le code suivant :

C.hh :

struct C
{
C( char const* p ) ;
C( C const& other ) ;

char const* pp ;
} ;

f.cc :

#include "C.hh"

inline
C::C( char const* p )
: pp( p )
{
}

inline
C::C( C const& other )
: pp( other.pp )
{
}

extern void g( C ) ;

int
main()
{
C c( "a string" ) ;
g( c ) ;
}


g.cc :

#include <iostream>
#include <ostream>
#include "C.hh"

void
g( C c )
{
std::cout << c.pp << 'n' ;
}

Je crois que de tel code est légal.

--
James Kanze GABI Software mailto:
Conseils en informatique orientée objet/ http://www.gabi-soft.fr
Beratung in objektorientierter Datenverarbeitung
11 rue de Rambouillet, 78460 Chevreuse, France, +33 (0)1 30 23 45 16

Avatar
Olivier
Bon voila les nouvautes

dans le cpp de TCoArticle j"ai fait

bool operator==(const TArticle &Art,const TArticle &Article){

return (Art.NomArt==Article.NomArt && Art.Description==Article.Description
&& Art.Categorie==Article.Categorie && Art.Prix==Article.Prix);

};
cependant mon test doit etre mon nouveau test dans searcharticle ?


bool bResúlse;
std::vector<TArticle*>::iterator i_end =_pArtList.end();
int j=0;

for(std::vector<TArticle*>::iterator
it=_pArtList.begin();it!=i_end;++it){


/* ancien test
if((*it)->NomArt==Art.NomArt && (*it)->Description==Art.Description &&
* / (*it)->Categorie==Art.Categorie && (*it)->Prix==Art.Prix){

if((*it)==&Art){ // ce tes ne marche pas quel autre test a faire ?

i=j;
bRes=true;
break;

}
j++;
}

return bRes;
}//@CODE_357

J'ai essaye en mode debug je ne rentre pas dans l'operateur surcharge

idem si je fais ceci

bool operator==(TArticle *pArticle,TArticle &Art){

return (Art.NomArt==pArticle->NomArt &&
Art.Description==pArticle->Description
&& Art.Categorie==pArticle->Categorie && Art.Prix==pArticle->Prix);

};


avec comme test if((*it)==&Art)




merci encore un fois de votre aide
Avatar
Luc Hermitte
Salut,

"Olivier" wrote in
news:3f2e3938$0$9587$:

if((*it)==&Art){ // ce tes ne marche pas quel autre test a faire
?


Tu compares encore des pointeurs et ce n'est pas ce que tu veux. Tu veux
comparer des articles et pas des pointeurs d'articles. Soit tu veux en
fait:
if (**it == Art)

it est un itérateur sur des Article*
*it est un pointeur sur un Article
**it est un Article

Et une fois que l'itérateur trouvé vérifie cette condition, tu n'as plus
qu'à faire le "la_liste.erase(it);" et basta!


Sinon ... tu sais que le code que j'ai posté marche ?


Autrement, on te demande explicitement de renvoyer des indices ? Parce
que tu continues à te compliquer la vie à contruire des indices que tu
reconvertiras par la suite en iterateurs ; autant manipuler des
iterateurs du début jusqu'à la fin.


--
Luc Hermitte <hermitte at free.fr>
FAQ de <news:fr.comp.lang.c++> :
<http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/>
Dejanews : <http://groups.google.com/advanced_group_search>

1 2 3 4