Paramètres de fonction : Passage par valeur/pointeur/reference ...
15 réponses
Bernie
bonjour,
on m'a posé la ? suivante et j'avoue qu'elle me fait avoir des doutes ...
les passage par pointeur et reference sont identique pour les types de
base et les objets.
Par contre, le passage par copie, que ce passe-t-il si un objet ne
dispose pas de constructeur par copie ?
Dans le cas ou on aurait pas besion d'un constructeur par copie :
Si l'objet possede un ptr vers un tableau dynamique, je suppose qu'il
faut aussi que l'objet dispose d'un ptr vers une section critique pour
que les routines de l'objet qui manipule ce tableau se verouillent les
unes les autres (appels venant de l'original et appel venant de la copie) ?
merci d'avance, j'aurais grandement besions de quelques éclaircissement.
Si par opérateur de copie, tu veux dire l'affectation
Je veux dire "operator=".
En revanche, le gestionnaire des transactions en fait bien une copie,
Mais par une fonction spéciale, pas par "operator=", si ?
kanze
Fabien LE LEZ wrote:
On 16 Nov 2005 00:08:29 -0800, "kanze" :
Si par opérateur de copie, tu veux dire l'affectation
Je veux dire "operator=".
En revanche, le gestionnaire des transactions en fait bien une copie,
Mais par une fonction spéciale, pas par "operator=", si ?
Par le constructeur de copie. C'est donc le cas dont j'ai parlé où on supporte la copie, mais non l'affectation.
En fait, il y a deux idiomes que j'utilise, selon le cas. Dans le premier (qui utilise quelque chose qui s'appelle « optimistic locking »), il n'y a que la copie -- quand le client obtient un objet pour la transaction, il obtient en fait une copie, et c'est la copie qu'il modifie. Á la fin de la transaction, on garde ou la copie, ou l'original, selon qu'il y a eu commit ou non. Dans l'autre, c'est la gestionnaire de transaction qui garde la copie, dans le cas de rollback, il peut utiliser l'affectation, si on tient à ce que l'objet garde la même adresse. (Sinon, et toujours dans le premier cas, les liens entre les objets doivent se faire de façon symbolique, et pour les suivre, il faut démander au gestionnaire des tableaux. Mais la gestion des locks dans un environement multi-thread est beaucoup plus simple dans le premier cas.)
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ wrote:
On 16 Nov 2005 00:08:29 -0800, "kanze" <kanze@gabi-soft.fr>:
Si par opérateur de copie, tu veux dire l'affectation
Je veux dire "operator=".
En revanche, le gestionnaire des transactions en fait
bien une copie,
Mais par une fonction spéciale, pas par "operator=", si ?
Par le constructeur de copie. C'est donc le cas dont j'ai parlé
où on supporte la copie, mais non l'affectation.
En fait, il y a deux idiomes que j'utilise, selon le cas. Dans
le premier (qui utilise quelque chose qui s'appelle « optimistic
locking »), il n'y a que la copie -- quand le client obtient un
objet pour la transaction, il obtient en fait une copie, et
c'est la copie qu'il modifie. Á la fin de la transaction, on
garde ou la copie, ou l'original, selon qu'il y a eu commit ou
non. Dans l'autre, c'est la gestionnaire de transaction qui
garde la copie, dans le cas de rollback, il peut utiliser
l'affectation, si on tient à ce que l'objet garde la même
adresse. (Sinon, et toujours dans le premier cas, les liens
entre les objets doivent se faire de façon symbolique, et pour
les suivre, il faut démander au gestionnaire des tableaux. Mais
la gestion des locks dans un environement multi-thread est
beaucoup plus simple dans le premier cas.)
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Si par opérateur de copie, tu veux dire l'affectation
Je veux dire "operator=".
En revanche, le gestionnaire des transactions en fait bien une copie,
Mais par une fonction spéciale, pas par "operator=", si ?
Par le constructeur de copie. C'est donc le cas dont j'ai parlé où on supporte la copie, mais non l'affectation.
En fait, il y a deux idiomes que j'utilise, selon le cas. Dans le premier (qui utilise quelque chose qui s'appelle « optimistic locking »), il n'y a que la copie -- quand le client obtient un objet pour la transaction, il obtient en fait une copie, et c'est la copie qu'il modifie. Á la fin de la transaction, on garde ou la copie, ou l'original, selon qu'il y a eu commit ou non. Dans l'autre, c'est la gestionnaire de transaction qui garde la copie, dans le cas de rollback, il peut utiliser l'affectation, si on tient à ce que l'objet garde la même adresse. (Sinon, et toujours dans le premier cas, les liens entre les objets doivent se faire de façon symbolique, et pour les suivre, il faut démander au gestionnaire des tableaux. Mais la gestion des locks dans un environement multi-thread est beaucoup plus simple dans le premier cas.)
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
kanze
Fabien LE LEZ wrote:
On Tue, 15 Nov 2005 18:30:24 +0100, "Alexandre" :
Cas particulier : pour un singleton, inutile de définir l'opérateur de copie...
Ce n'est pas un "cas particulier" : un singleton est non-copiable (puisque par définition il n'en existe qu'une instance), donc ni le constructeur de copie, ni l'opérateur de copie ne doivent être définis.
Et pour que le compilateur ne les définisse pas pour toi, il faut que tu les déclares explicitement (privés) tous les deux.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ wrote:
On Tue, 15 Nov 2005 18:30:24 +0100, "Alexandre"
<alex.g@netcourrier.com>:
Cas particulier : pour un singleton, inutile de définir
l'opérateur de copie...
Ce n'est pas un "cas particulier" : un singleton est
non-copiable (puisque par définition il n'en existe qu'une
instance), donc ni le constructeur de copie, ni l'opérateur de
copie ne doivent être définis.
Et pour que le compilateur ne les définisse pas pour toi, il
faut que tu les déclares explicitement (privés) tous les deux.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Cas particulier : pour un singleton, inutile de définir l'opérateur de copie...
Ce n'est pas un "cas particulier" : un singleton est non-copiable (puisque par définition il n'en existe qu'une instance), donc ni le constructeur de copie, ni l'opérateur de copie ne doivent être définis.
Et pour que le compilateur ne les définisse pas pour toi, il faut que tu les déclares explicitement (privés) tous les deux.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ
On 16 Nov 2005 23:44:05 -0800, "kanze" :
quand le client obtient un objet pour la transaction, il obtient en fait une copie, et c'est la copie qu'il modifie.
J'ai un peu de mal à comprendre, sur ce coup-là.
Si j'ai bien compris, le client va chercher un objet dans un tableau (ou équivalent), l'obtient par copie, fait ce qu'il veut avec, puis éventuellement copie l'objet modifié dans le tableau.
J'ai dû un peu trop simplifier, car pour le coup, étant donné qu'on travaille sur des copies, je ne vois pas pourquoi la classe n'a pas une sémantique de valeur pure et simple.
On 16 Nov 2005 23:44:05 -0800, "kanze" <kanze@gabi-soft.fr>:
quand le client obtient un
objet pour la transaction, il obtient en fait une copie, et
c'est la copie qu'il modifie.
J'ai un peu de mal à comprendre, sur ce coup-là.
Si j'ai bien compris, le client va chercher un objet dans un tableau
(ou équivalent), l'obtient par copie, fait ce qu'il veut avec, puis
éventuellement copie l'objet modifié dans le tableau.
J'ai dû un peu trop simplifier, car pour le coup, étant donné qu'on
travaille sur des copies, je ne vois pas pourquoi la classe n'a pas
une sémantique de valeur pure et simple.
quand le client obtient un objet pour la transaction, il obtient en fait une copie, et c'est la copie qu'il modifie.
J'ai un peu de mal à comprendre, sur ce coup-là.
Si j'ai bien compris, le client va chercher un objet dans un tableau (ou équivalent), l'obtient par copie, fait ce qu'il veut avec, puis éventuellement copie l'objet modifié dans le tableau.
J'ai dû un peu trop simplifier, car pour le coup, étant donné qu'on travaille sur des copies, je ne vois pas pourquoi la classe n'a pas une sémantique de valeur pure et simple.
kanze
Fabien LE LEZ wrote:
On 16 Nov 2005 23:44:05 -0800, "kanze" :
quand le client obtient un objet pour la transaction, il obtient en fait une copie, et c'est la copie qu'il modifie.
J'ai un peu de mal à comprendre, sur ce coup-là.
Si j'ai bien compris, le client va chercher un objet dans un tableau (ou équivalent), l'obtient par copie, fait ce qu'il veut avec, puis éventuellement copie l'objet modifié dans le tableau.
C'est à peu près ça. Quand on utilise des transactions, il faut bien que les objets soient introduits dans la transaction exprès. La plupart du temps, quand on utilise les transactions, c'est qu'on a des clients (au programme, ou à l'application) externe, et que donc on a un moyen d'identifier et de trouver l'objet autrement que par son adresse. Ce qu'on implémente prèsqu'à coup sûr au moyen d'un tableau associatif (tableau haché, std::map, etc.).
On wrappe donc le tableau, et quand le client en démande un objet, il en reçoit en fait une copie. Dans le commit, le client rend tous les objets (ses copies) aux tableaux, qui remplacent l'objet réelement dans le tableau avec la nouvelle copie.
J'ai dû un peu trop simplifier, car pour le coup, étant donné qu'on travaille sur des copies, je ne vois pas pourquoi la classe n'a pas une sémantique de valeur pure et simple.
Surtout parce que les objets sont en général polymorphique. Et la sémantique de valeur ne marche pas très bien avec les objets polymorphiques. Et aussi parce qu'on ne veut pas la copier à l'intérieur de la transaction. Si le client en modifie deux champs, il faut qu'il les modifie bien dans le même objet. L'identité de l'objet est significative. Il y a au plus deux instances de l'objet, une qui représente sa valeur avant la transaction, et une qui représente sa valeur (qui peut changer de façon non atomique) dans la transaction.
Cette solution sert surtout dans les serveurs multi-thread, où il peut y avoir plusieurs transactions actives à la fois. Dans ce cas-là, il y a un « timestamp » associé à chaque objet, qui représente la dernière modification. Ce timestamp est copié dans l'objet qu'on rend au client ; il n'est jamais modifié par le client. Lors du commit, le gestionnaire des transactions vérifie que les timestamps dans les objets rendus sont identique à ceux dans les tableaux ; sinon, la transaction échoue. Ensuite, il génère un nouveau timestamp, l'affecte à tous les objets rendus, et les remplace dans les tableaux.
L'avantage, c'est que je n'ai pas besoin d'un lock par objet, avec les risques de deadlock que ça implique. (Le client 1 démande l'objet A, puis l'objet B. Le client 2 démande l'objet B, puis l'objet A. Si le client 1 obtient le lock pour l'objet A avant que le client 2 le démande, et le client 2 obtient le lock pour l'objet B avant que le client 1 le démande, on ne va pas très loin.) Sans qu'on bloque toutes les tables, ni même toute une table, pour très longtemps. (Le temps de sortir un objet, ou le temps de les rémettre.)
Le dèsavantage, évidemment, c'est qu'il faut que le client puisse traiter les cas d'échec qui en résulte. Mais quand la probabilité que deux clients essaient de modifier le même objet au même temps est faible, ça vaut la peine.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Fabien LE LEZ wrote:
On 16 Nov 2005 23:44:05 -0800, "kanze" <kanze@gabi-soft.fr>:
quand le client obtient un
objet pour la transaction, il obtient en fait une copie, et
c'est la copie qu'il modifie.
J'ai un peu de mal à comprendre, sur ce coup-là.
Si j'ai bien compris, le client va chercher un objet dans un
tableau (ou équivalent), l'obtient par copie, fait ce qu'il
veut avec, puis éventuellement copie l'objet modifié dans le
tableau.
C'est à peu près ça. Quand on utilise des transactions, il faut
bien que les objets soient introduits dans la transaction
exprès. La plupart du temps, quand on utilise les transactions,
c'est qu'on a des clients (au programme, ou à l'application)
externe, et que donc on a un moyen d'identifier et de trouver
l'objet autrement que par son adresse. Ce qu'on implémente
prèsqu'à coup sûr au moyen d'un tableau associatif (tableau
haché, std::map, etc.).
On wrappe donc le tableau, et quand le client en démande un
objet, il en reçoit en fait une copie. Dans le commit, le client
rend tous les objets (ses copies) aux tableaux, qui remplacent
l'objet réelement dans le tableau avec la nouvelle copie.
J'ai dû un peu trop simplifier, car pour le coup, étant donné
qu'on travaille sur des copies, je ne vois pas pourquoi la
classe n'a pas une sémantique de valeur pure et simple.
Surtout parce que les objets sont en général polymorphique. Et
la sémantique de valeur ne marche pas très bien avec les objets
polymorphiques. Et aussi parce qu'on ne veut pas la copier à
l'intérieur de la transaction. Si le client en modifie deux
champs, il faut qu'il les modifie bien dans le même objet.
L'identité de l'objet est significative. Il y a au plus deux
instances de l'objet, une qui représente sa valeur avant la
transaction, et une qui représente sa valeur (qui peut changer
de façon non atomique) dans la transaction.
Cette solution sert surtout dans les serveurs multi-thread, où
il peut y avoir plusieurs transactions actives à la fois. Dans
ce cas-là, il y a un « timestamp » associé à chaque objet, qui
représente la dernière modification. Ce timestamp est copié dans
l'objet qu'on rend au client ; il n'est jamais modifié par le
client. Lors du commit, le gestionnaire des transactions vérifie
que les timestamps dans les objets rendus sont identique à ceux
dans les tableaux ; sinon, la transaction échoue. Ensuite, il
génère un nouveau timestamp, l'affecte à tous les objets rendus,
et les remplace dans les tableaux.
L'avantage, c'est que je n'ai pas besoin d'un lock par objet,
avec les risques de deadlock que ça implique. (Le client 1
démande l'objet A, puis l'objet B. Le client 2 démande l'objet
B, puis l'objet A. Si le client 1 obtient le lock pour l'objet A
avant que le client 2 le démande, et le client 2 obtient le lock
pour l'objet B avant que le client 1 le démande, on ne va pas
très loin.) Sans qu'on bloque toutes les tables, ni même toute
une table, pour très longtemps. (Le temps de sortir un objet, ou
le temps de les rémettre.)
Le dèsavantage, évidemment, c'est qu'il faut que le client
puisse traiter les cas d'échec qui en résulte. Mais quand la
probabilité que deux clients essaient de modifier le même objet
au même temps est faible, ça vaut la peine.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
quand le client obtient un objet pour la transaction, il obtient en fait une copie, et c'est la copie qu'il modifie.
J'ai un peu de mal à comprendre, sur ce coup-là.
Si j'ai bien compris, le client va chercher un objet dans un tableau (ou équivalent), l'obtient par copie, fait ce qu'il veut avec, puis éventuellement copie l'objet modifié dans le tableau.
C'est à peu près ça. Quand on utilise des transactions, il faut bien que les objets soient introduits dans la transaction exprès. La plupart du temps, quand on utilise les transactions, c'est qu'on a des clients (au programme, ou à l'application) externe, et que donc on a un moyen d'identifier et de trouver l'objet autrement que par son adresse. Ce qu'on implémente prèsqu'à coup sûr au moyen d'un tableau associatif (tableau haché, std::map, etc.).
On wrappe donc le tableau, et quand le client en démande un objet, il en reçoit en fait une copie. Dans le commit, le client rend tous les objets (ses copies) aux tableaux, qui remplacent l'objet réelement dans le tableau avec la nouvelle copie.
J'ai dû un peu trop simplifier, car pour le coup, étant donné qu'on travaille sur des copies, je ne vois pas pourquoi la classe n'a pas une sémantique de valeur pure et simple.
Surtout parce que les objets sont en général polymorphique. Et la sémantique de valeur ne marche pas très bien avec les objets polymorphiques. Et aussi parce qu'on ne veut pas la copier à l'intérieur de la transaction. Si le client en modifie deux champs, il faut qu'il les modifie bien dans le même objet. L'identité de l'objet est significative. Il y a au plus deux instances de l'objet, une qui représente sa valeur avant la transaction, et une qui représente sa valeur (qui peut changer de façon non atomique) dans la transaction.
Cette solution sert surtout dans les serveurs multi-thread, où il peut y avoir plusieurs transactions actives à la fois. Dans ce cas-là, il y a un « timestamp » associé à chaque objet, qui représente la dernière modification. Ce timestamp est copié dans l'objet qu'on rend au client ; il n'est jamais modifié par le client. Lors du commit, le gestionnaire des transactions vérifie que les timestamps dans les objets rendus sont identique à ceux dans les tableaux ; sinon, la transaction échoue. Ensuite, il génère un nouveau timestamp, l'affecte à tous les objets rendus, et les remplace dans les tableaux.
L'avantage, c'est que je n'ai pas besoin d'un lock par objet, avec les risques de deadlock que ça implique. (Le client 1 démande l'objet A, puis l'objet B. Le client 2 démande l'objet B, puis l'objet A. Si le client 1 obtient le lock pour l'objet A avant que le client 2 le démande, et le client 2 obtient le lock pour l'objet B avant que le client 1 le démande, on ne va pas très loin.) Sans qu'on bloque toutes les tables, ni même toute une table, pour très longtemps. (Le temps de sortir un objet, ou le temps de les rémettre.)
Le dèsavantage, évidemment, c'est qu'il faut que le client puisse traiter les cas d'échec qui en résulte. Mais quand la probabilité que deux clients essaient de modifier le même objet au même temps est faible, ça vaut la peine.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34