C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

wisdom of using const references as data members

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Dave Moore
Guest





PostPosted: Tue Jan 18, 2005 11:09 pm    Post subject: wisdom of using const references as data members Reply with quote



I have been using const references as data members in my classes for some
time now, and although I don't seem to have any problems thus far, it still
gives me the willies. This is because the external object referred to may
change its state "unexpectedly" (i.e. without announcing itself),
potentially changing the behavior of the enclosing class in a "silent"
fashion. (I am also familiar with object lifetime issues which can
potentially create dangling references, so that is not really what I am
trying to get at in this post.) I am about to make a major upgrade to one
of my programs, for which my current design involves introducing several
more classes that have const reference members. Before I do this, I wanted
to step back and review the general wisdom of the technique.

It certainly seems like there are times when using const reference members
is "the right thing to do", for example when it helps you to avoid exposing
the implementation of a class. Consider the following example, where the
implementation of a particular type of calculation requires a helper class,
which is not part of its public interface. This suggests enclosing a helper
object in the class as a data member, as opposed to passing a reference as
an argument. However, when several calculation objects can be "helped" by
the same helper object, it does not make sense to store a copy in each
calculation object. Thus we arrive at:

class calculation {
public:
calculation(const helper& h) : _helper(h) {}
// ...
private:
const calc_helper& _helper; // calculation does not modify _helper
};

With this design we also get the automatic "optimization" that when we
change the external helper object, it is instantly updated in all of the
calculation objects (which is the particular reason I am expending effort to
make this technique work in my code). Of course this "tight coupling" of
the helper and calculation objects (not classes) is a double-edged sword,
because it can introduce order of execution dependencies into the code,
which may then pop up at run-time in mysterious ways.

So my question is, are there any idioms or patterns out there for handling
(or even eliminating) the use of const references as data members in a safe
way, or at least in the safest possible way? I have searched around in my
books and on the web and I have not been able to find anything particularly
useful. Any suggestions?

TIA,

Dave Moore



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Back to top
Matthew Herrmann
Guest





PostPosted: Wed Jan 19, 2005 11:56 pm    Post subject: Re: wisdom of using const references as data members Reply with quote



Dave Moore wrote:
Quote:
I have been using const references as data members in my classes for
some
time now, and although I don't seem to have any problems thus far, it
still
gives me the willies. This is because the external object referred
to may
change its state "unexpectedly" (i.e. without announcing itself),
potentially changing the behavior of the enclosing class in a
"silent"
fashion. (I am also familiar with object lifetime issues which can
potentially create dangling references, so that is not really what I
am
trying to get at in this post.) I am about to make a major upgrade
to one
of my programs, for which my current design involves introducing
several
more classes that have const reference members. Before I do this, I
wanted
to step back and review the general wisdom of the technique.

It certainly seems like there are times when using const reference
members
is "the right thing to do", for example when it helps you to avoid
exposing
the implementation of a class. Consider the following example, where
the
implementation of a particular type of calculation requires a helper
class,
which is not part of its public interface. This suggests enclosing a
helper
object in the class as a data member, as opposed to passing a
reference as
an argument. However, when several calculation objects can be
"helped" by
the same helper object, it does not make sense to store a copy in
each
calculation object. Thus we arrive at:

class calculation {
public:
calculation(const helper& h) : _helper(h) {}
// ...
private:
const calc_helper& _helper; // calculation does not modify
_helper
};

With this design we also get the automatic "optimization" that when
we
change the external helper object, it is instantly updated in all of
the
calculation objects (which is the particular reason I am expending
effort to
make this technique work in my code). Of course this "tight
coupling" of
the helper and calculation objects (not classes) is a double-edged
sword,
because it can introduce order of execution dependencies into the
code,
which may then pop up at run-time in mysterious ways.

So my question is, are there any idioms or patterns out there for
handling
(or even eliminating) the use of const references as data members in
a safe
way, or at least in the safest possible way? I have searched around
in my
books and on the web and I have not been able to find anything
particularly
useful. Any suggestions?

The key issue is this: "calculation" is in a dependency relationship
with "helper". There are fields, which, whenever helper changes, must
be updated. You could draw these relationships on a sheet of paper with
a graph. You need to make sure that whenever the source changes, the
dependent updates change. The naiive way to do this is to use the
Listener design pattern, and recalculate on all changes.

The better way is to use a "late-as-possible" update approach which
only updates the target on first access to the calculated results:

* Source changes
* Source notifies target
* Target sets dirty flag to true
* Before accessing any calculated values in target, the dirty flag is
checked. If the dirty flag is true, then recalculate and set to false.

This approach is particularly important in deeply embedded hierarchies
where nested Listener connections cause spiralling performance hits.
The "late-as-possible" approach also prevents unintended calculations
being kicked off in destructors.

HTH,

Matthew Herrmann


[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.