473,378 Members | 1,680 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Read-only, as opposed to const member

Back when I read my first C++ book, I was given the following scenario:

class Cheese
{
public:

int number_of_holes;

int colour;

};
The thing is, you want the "user" of this class to be able to read from the
two above variables, but no be able to change them. The book retardly gave
the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

int GetNumberOfHoles(void);

int GetColour(void);
};

What do yous think of the following:
class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes;
}

const int& GetColour(void)
{
return colour;
}

};

int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
}
I wonder was so many books think they have to show you the stupid way before
they give you the lean, mean, efficient way.
-JKop
Jul 22 '05 #1
39 3018


An even better idea!:
class Cheese
{
private:

int prv_number_of_holes;

int prv_colour;

public:

const int& number_of_holes;

const int& colour;

Cheese(void) : number_of_holes(prv_number_of_holes),
colour(prv_colour)
{
;
}

void Blah(void)
{
prv_number_of_holes = 52;

prv_colour = 2;
}

};
int main(void)
{
Cheese chalk;

TakesInt(chalk.number_of_holes);

chalk.number_of_holes = 52; //Compile error
}
This way, the actual class member functions and also friend functions have
write-access to these member variables, while the "user" only has read-only
access!
-JKop
Jul 22 '05 #2
In message <z%*****************@news.indigo.ie>, JKop <NU**@NULL.NULL>
writes
Back when I read my first C++ book, I was given the following scenario:

class Cheese
{
public:

int number_of_holes;

int colour;

};
The thing is, you want the "user" of this class to be able to read from the
two above variables, but no be able to change them. The book retardly gave
the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

int GetNumberOfHoles(void);

int GetColour(void);
Both of those should be const functions, and the "void" is unidiomatic.};

What do yous think of the following:
class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes;
}

const int& GetColour(void)
{
return colour;
}
I think those should be const functions, too, and you don't need the
"void".
};

int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
Pointless. Didn't you mean

something = chalk.GetNumberOfHoles();

? There's an important difference.}
I wonder was so many books think they have to show you the stupid way before
they give you the lean, mean, efficient way.


Because it's the safe way? Once you start returning references, the
next thing is to try returning references to temporaries, with hilarious
consequences.

What do you think you would gain by returning a reference?

I doubt that returning an int by value is likely to be any more obese or
less efficient than returning a const reference. Even if you'd
substituted some class with a costly copy constructor, don't forget that
ultimately you want to _do_ something with the value of whatever the
function returns, or why call it in the first place? And that means
that somewhere or other there's likely to be a copy operation anyway,
whether you return a value or a reference. Given the existence of return
value optimisation, the difference in cost may be less than you
expected.

--
Richard Herring
Jul 22 '05 #3
JKop wrote:

What do yous think of the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes;
}

const int& GetColour(void)
{
return colour;
}

};

int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
}

I wonder was so many books think they have to show you the stupid way before
they give you the lean, mean, efficient way.


On most typical machines this is no more efficient then returning
the values directly. There is literally no point in replacing
a pass by value with a pass per reference for builtin types
like int, double, char, etc...
--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #4
JKop wrote:

An even better idea!:
class Cheese
{
private:

int prv_number_of_holes;

int prv_colour;

public:

const int& number_of_holes;

const int& colour;

Cheese(void) : number_of_holes(prv_number_of_holes),
colour(prv_colour)
{
;
}

void Blah(void)
{
prv_number_of_holes = 52;

prv_colour = 2;
}

};
int main(void)
{
Cheese chalk;

TakesInt(chalk.number_of_holes);

chalk.number_of_holes = 52; //Compile error
}

This way, the actual class member functions and also friend functions have
write-access to these member variables, while the "user" only has read-only
access!


and when the internals of that class Cheese change, all the code that uses
that class breaks immediatly. Congratulations: you just found a clever way
of breaking the concept of encapsulation :-)

Trust your compilers optimizer!
He may do more then you expect.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #5
JKop wrote:
Back when I read my first C++ book, I was given the following scenario:

class Cheese
{
public:

int number_of_holes;

int colour;

};
The thing is, you want the "user" of this class to be able to read from the
two above variables, but no be able to change them. The book retardly gave
the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

int GetNumberOfHoles(void);

int GetColour(void);
};

What do yous think of the following:
class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes;
}

const int& GetColour(void)
{
return colour;
}

};

int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
}

I wonder was so many books think they have to show you the stupid way before
they give you the lean, mean, efficient way.


If those funtions are inlined and if you use an optimizing compiler it
will most likely not make a difference whether you return by reference
or return by value. In trivial cases like this example the contents of
the main() function would most likely be completely optimized away
(since everything is inline in this example the compiler can determine
that there are no observable side effects). In cases where the main()
function uses the return values (so the calls to the chalk object can
not be optimized away), the compiler will most likely generate exactly
the same code for both cases.

Note that the optimization story changes when the member functions of
the Cheese class are not inlined (i.e. when the implementation of these
member functions are in a different translation unit). In this case the
compiler does not know what happens inside the member functions, and
therefore the optimizer must be conservative and must call the functions.

For simple types (like int), that have zero construction and destruction
overhead and have very low copy overhead (about the same as copying
pointers which typically happens when dealing with references), there is
most likely no performance gain by using references. In fact in some
cases returning by reference instead of returning by value can even be
slower (taking a peek at assembly code generated by the compiler can be
very instructive). Of course if you have objects that are costly to
copy(construct) using references can give significant performance
benefits, and should be used whenever appropriate.

The reason why books start with the return by value example probably for
educational reasons; start simple first and discuss the more advanced
topics later. Also note that performance is only one of the lofty goals
to pursue. The net effect of the micro optimizations you are after is
usually quite small or even immeasurable. In my experience you are lucky
if you can improve performance that way by more than 20% (there are
exceptions but those are rare). On the other hand it is not rare for
high-level optimizations (e.g. better algorithms) to improve performance
by more than an order of magnitude. You have to consider carefully on
what you spend time. That being said there is obviously no point in
writing needlessly inefficient code.

--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
Jul 22 '05 #6
On Thu, 24 Jun 2004 10:26:39 GMT, JKop <NU**@NULL.NULL> wrote:
Back when I read my first C++ book, I was given the following scenario:

class Cheese
{
public:

int number_of_holes;

int colour;

};
The thing is, you want the "user" of this class to be able to read from the
two above variables, but no be able to change them. The book retardly gave
the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

int GetNumberOfHoles(void);

int GetColour(void);
};
Yes, they miss the const qualification on the member functions, which
is a bad idea.
What do yous think of the following:
class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes;
}

const int& GetColour(void)
{
return colour;
}

};
It also misses the const qualification. What's more, the return by
reference exposes the implementation of Cheese, since the class needs
int member variables to return references to. What if you decide to
store the colour as a class internally? You don't want to have to
change the interface.

In addition, returning built-ins by reference is usually a
pessimization - it is slower than return by value, at least until the
optimizer turns it back into return by value!
int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
}
I wonder was so many books think they have to show you the stupid way before
they give you the lean, mean, efficient way.


Neither way is good, but yours is actually more stupid.

Tom
--
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Jul 22 '05 #7
Peter van Merkerk posted:
You have to consider carefully on what you spend time. That being said
there is obviously no point in writing needlessly inefficient code.

I have all the time in the world! Ahh... the joys of unemployment.
-JKop
Jul 22 '05 #8
Richard Herring posted:
In message <z%*****************@news.indigo.ie>, JKop <NU**@NULL.NULL>
writes
Back when I read my first C++ book, I was given the following scenario:

class Cheese
{
public:

int number_of_holes;

int colour;

};
The thing is, you want the "user" of this class to be able to read from
the two above variables, but no be able to change them. The book
retardly gave the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

int GetNumberOfHoles(void);

int GetColour(void);
Both of those should be const functions, and the "void" is unidiomatic.


int GetNumberOfHoles(void) const;

int GetColour(void) const;
"unidiomatic" is a subjective term.
};

What do yous think of the following:
class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes; }

const int& GetColour(void)
{
return colour; }


I think those should be const functions, too, and you don't need the
"void".

const int& GetNumberOfHoles(void) const;

const int& GetColour(void) const;

I am fully aware that I don't need the "void".
};

int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
Pointless. Didn't you mean

something = chalk.GetNumberOfHoles();

No.

I didn't suggest there was a point.


? There's an important difference.
}
I wonder was so many books think they have to show you the stupid way
before they give you the lean, mean, efficient way.
Because it's the safe way? Once you start returning references, the
next thing is to try returning references to temporaries, with
hilarious consequences.

Hence the absence of the returning of references to temporaries.

What do you think you would gain by returning a reference?

I doubt that returning an int by value is likely to be any more obese
or less efficient than returning a const reference. Even if you'd
substituted some class with a costly copy constructor, don't forget
that ultimately you want to _do_ something with the value of whatever
the function returns, or why call it in the first place? And that
means that somewhere or other there's likely to be a copy operation
anyway, whether you return a value or a reference. Given the existence
of return value optimisation, the difference in cost may be less than
you expected.

If I'm pedantic about it, there's greater probability of the reference form
being more efficent than the return-by-value form, as the return-by-value
form, under the duress of the Standard, *may* create a temporary.
-JKop

Jul 22 '05 #9
Karl Heinz Buchegger posted:
and when the internals of that class Cheese change, all the code that
uses that class breaks immediatly. Congratulations: you just found a
clever way of breaking the concept of encapsulation :-)

Trust your compilers optimizer!
He may do more then you expect.

So long as you have read-only variables/objects, it should be grand.
-JKop
Jul 22 '05 #10
In message <AM*****************@news.indigo.ie>, JKop <NU**@NULL.NULL>
writes
Richard Herring posted:
In message <z%*****************@news.indigo.ie>, JKop <NU**@NULL.NULL>
writes
Back when I read my first C++ book, I was given the following scenario:

class Cheese
{
public:

int number_of_holes;

int colour;

};
The thing is, you want the "user" of this class to be able to read from
the two above variables, but no be able to change them. The book
retardly gave the following:

class Cheese
{
private:

int number_of_holes;

int colour;

public:

int GetNumberOfHoles(void);

int GetColour(void);
Both of those should be const functions, and the "void" is unidiomatic.


int GetNumberOfHoles(void) const;

int GetColour(void) const;

"unidiomatic" is a subjective term.


Of course. That's why I didn't say "wrong". Nevertheless, it's more to
type and marks you as possibly being an unregenerate C programmer.
};
What do yous think of the following:
class Cheese
{
private:

int number_of_holes;

int colour;

public:

const int& GetNumberOfHoles(void)
{
return number_of_holes; }

const int& GetColour(void)
{
return colour; }


I think those should be const functions, too, and you don't need the
"void".

const int& GetNumberOfHoles(void) const;

const int& GetColour(void) const;

I am fully aware that I don't need the "void".


Good. Save yourself a few keystrokes.
};

int main(void)
{
Cheese chalk;

chalk.GetNumberOfHoles();
Pointless. Didn't you mean

something = chalk.GetNumberOfHoles();


No.

I didn't suggest there was a point.


I thought you were trying to make one? If you discard the results of the
side-effect-free function call, the whole thing could be as-if'd away to
nothing.
? There's an important difference.
}

I wonder was so many books think they have to show you the stupid way
before they give you the lean, mean, efficient way.


Because it's the safe way? Once you start returning references, the
next thing is to try returning references to temporaries, with
hilarious consequences.


Hence the absence of the returning of references to temporaries.


Well, good for you.
What do you think you would gain by returning a reference?

I doubt that returning an int by value is likely to be any more obese
or less efficient than returning a const reference. Even if you'd
substituted some class with a costly copy constructor, don't forget
that ultimately you want to _do_ something with the value of whatever
the function returns, or why call it in the first place? And that
means that somewhere or other there's likely to be a copy operation
anyway, whether you return a value or a reference. Given the existence
of return value optimisation, the difference in cost may be less than
you expected.


If I'm pedantic about it, there's greater probability of the reference form
being more efficent than the return-by-value form, as the return-by-value
form, under the duress of the Standard, *may* create a temporary.


And it may not (strange meaning of "duress" you have there.) But getting
a value from the reference involves an extra indirection behind the
scenes, so there's a definite inefficiency there.
--
Richard Herring
Jul 22 '05 #11
For accessors I prefer the return-by-value approach rather than the
return-by-reference approach.

The return-by-reference approach I believe creates an implementation
dependency.

In your case you are returning references to integers. This seems to work out
fine because you have chosen to store integers and thus have integers with
which to initialize your references.

What happens though if you decide you want to modify your class to change how
and/or where your data is stored?

Where then is the integer to initialize your reference going to come from?

If you no longer have an integer with which to initialize a reference are you
going to change the return type of your accessor? Clients might not
appreciate that.

I think returning by value alleviates some of these problems. The underlying
storage mechanism can change at will. So long as the data represented still
conceptually represents an integer than changes to the implementation need not
have great impact.

As an aside, I also prefer the return-by-value for safety reasons. Your
accessor returns a const reference which of course communicates to its caller
that it may not modify the referenced data. That constness though is easily
cast away which can result in modifications that bypass any "set" functions
that might be in place. Returning by value seems to also alleviate the
possibility that your object could somehow be corrupted.

Of course some people say you shouldn't write code that guards against
deliberate misuse...that writers of such code deserve whatever fate befalls
them.
Jul 22 '05 #12
DaKoadMunky posted:
For accessors I prefer the return-by-value approach rather than the
return-by-reference approach.

The return-by-reference approach I believe creates an implementation
dependency.

In your case you are returning references to integers. This seems to
work out fine because you have chosen to store integers and thus have
integers with which to initialize your references.

What happens though if you decide you want to modify your class to
change how and/or where your data is stored?

Where then is the integer to initialize your reference going to come
from?
I don't understand your logic.

Let's say I change the int to a double .

A) MY CODE: Change the "const int&" to "const double&"

B) YOUR CODE: Change "int GetColour(void)" to "double GetColour(void)".
Karl mentioned something about this too, but I still don't see your
argument.


If you no longer have an integer with which to initialize a reference
are you going to change the return type of your accessor? Clients
might not appreciate that.
To which code do you refer? My first one with member functions that return
const references, or my second one which has public const member references
which are initialized with private non-const variables?
As an aside, I also prefer the return-by-value for safety reasons.
Your accessor returns a const reference which of course communicates to
its caller that it may not modify the referenced data. That constness
though is easily cast away which can result in modifications that
bypass any "set" functions that might be in place. Returning by value
seems to also alleviate the possibility that your object could somehow
be corrupted.


This could lead into the realms of whether there should be const in C++ at
all. There's no const in Python, and their official reason is "We're all
consenting adults here!".
-JKop
Jul 22 '05 #13
Karl Heinz Buchegger posted:
and when the internals of that class Cheese change, all the code that
uses that class breaks immediatly. Congratulations: you just found a
clever way of breaking the concept of encapsulation :-)


I really don't understand this at all. Could you please be more specific?

-JKop
Jul 22 '05 #14
In message <qC*****************@news.indigo.ie>, JKop <NU**@NULL.NULL>
writes
DaKoadMunky posted:
For accessors I prefer the return-by-value approach rather than the
return-by-reference approach.

The return-by-reference approach I believe creates an implementation
dependency.

In your case you are returning references to integers. This seems to
work out fine because you have chosen to store integers and thus have
integers with which to initialize your references.

What happens though if you decide you want to modify your class to
change how and/or where your data is stored?

Where then is the integer to initialize your reference going to come
from?


I don't understand your logic.

Let's say I change the int to a double .

A) MY CODE: Change the "const int&" to "const double&"

B) YOUR CODE: Change "int GetColour(void)" to "double GetColour(void)".


No, that's not what he's saying.

At the moment you have

int & GetColour() const { return colour; }
- or -
int GetColour() const { return colour; }

What happens if you move to a more sophisticated colour model? Instead
of storing an int, maybe you need to compute something from the user's
choice, the available palette, the kind of display device etc...

OK, add some functionality to compute it:

private:
int ComputeComplicatedColour(int userColour, palette p, display d)
const;

If returning a value, no problem; just change your access function to
this:
int GetColour() const
{ return ComputeComplicatedColour(colour, palette, device); }

But if you're returning a reference:
int & GetColour() const
{ return reference to what??? }

--
Richard Herring
Jul 22 '05 #15
JKop wrote:
Back when I read my first C++ book, I was given the following scenario:

class Cheese {
public:
int number_of_holes;
int colour;
};

The thing is,
you want the "user" of this class to be able to read from the
two above variables, but no be able to change them.
The book retardly gave the following:

class Cheese {
private:
int number_of_holes;
int colour;
public:
int GetNumberOfHoles(void);
int GetColour(void);
};

What do yous think of the following:

class Cheese {
private:
int number_of_holes;
int colour;
public:
const int& GetNumberOfHoles(void) {
return number_of_holes;
}
const int& GetColour(void) {
return colour;
}
Yes, this is the preferred method
when returning a reference to a large object
instead of a small object like an int.

Actually, I might have written

const int& holes(void) const {
return number_of_holes;
}
const int& color(void) const {
return colour;
}

if your intent is *not* to change any part of the object.

};

int main(void) {
Cheese chalk;
chalk.GetNumberOfHoles(); // . . .
return 0;
}
I wonder was so many books think they have to show you the stupid way
before they give you the lean, mean, efficient way.


Is it stupid?

int main(int argc, char* argv[]) {
Cheese* pCheese = new Cheese;
const int& holes = pCheese->holes()
delete pCheese;
// holes is no longer a valid reference
std::cout << holes << " = holes" << srd::endl;
// undefined behavior
return 0;
}
Jul 22 '05 #16
E. Robert Tisdale posted:
int main(void) {
Cheese chalk;
chalk.GetNumberOfHoles();

// . . .
return 0;
}


The "return 0;" is a matter of preference. I don't put it in because I don't
give a hoot about my program returning anything.

I wonder was so many books think they have to show you the stupid way
before they give you the lean, mean, efficient way.


Is it stupid?

int main(int argc, char* argv[]) {
Cheese* pCheese = new Cheese;
const int& holes = pCheese->holes()
delete pCheese;
// holes is no longer a valid reference
std::cout << holes << " = holes" << srd::endl;
// undefined behavior

Which is exactly the same as doing something as equally as stupid as:

pCheese->MakeEaterSick();
I notice how you didn't complain about that.

---
Anyway, I entirely retract my original code. I've replaced it with the
supplementary code I posted.
-JKop

Jul 22 '05 #17
JKop posted:
E. Robert Tisdale posted:

int main(int argc, char* argv[]) {
Cheese* pCheese = new Cheese;
const int& holes = pCheese->holes()
delete pCheese;
// holes is no longer a valid reference
std::cout << holes << " = holes" << srd::endl; // undefined
behavior

I think I missed your point.

Are you referring to how one can bind a reference to the return value of a
return-by-value function, and then have not worry about the variable/object
ever going out of scope. Whereas with the above code, even though the
"holes" reference in main is still in scope, the variable to which it refers
is OUT of scope.

Good point. But then again, it's clearly evident that my code returns a
reference, as opposed to returning by value.

-JKop
Jul 22 '05 #18
Richard Herring wrote:
What happens if you move to a more sophisticated colour model? Instead
of storing an int, maybe you need to compute something from the user's
choice, the available palette, the kind of display device etc...
No, you create a new or derived class.
OK, add some functionality to compute it:

private:
int ComputeComplicatedColour(int userColour, palette p, display d)
const;

If returning a value, no problem; just change your access function to
this:
int GetColour() const
{ return ComputeComplicatedColour(colour, palette, device); }


You have now just changed the behavior of the original function with respect to
performance, which is a very real and tangible change.

This is why I advocate const reference member accessors to simple data -- it
*guarantees* that access to the underlying data is immediate and absolute, and
will stay that way. It doesn't break encapsulation as some have said, but
creates an immutable contract between the class designer and class user. You
can't get that w/ functions.
Jul 22 '05 #19

"JKop" <NU**@NULL.NULL> wrote in message
news:BE*****************@news.indigo.ie...
Karl Heinz Buchegger posted:
and when the internals of that class Cheese change, all the code that
uses that class breaks immediatly. Congratulations: you just found a
clever way of breaking the concept of encapsulation :-)


I really don't understand this at all. Could you please be more specific?

-JKop


Consider, boss says to you 'I no longer want you to store the colour in the
Cheese object. We have too many cheese objects and they're are taking up too
much memory. People aren't interested in the colour of cheese much, most of
the time its yellow anyway.'

'So what were are going to do instead is store the cheese colour in a
database and you can access the database when someone calls GetColour. Just
to make things really easy for you the database department have written this
handy API for you do use.'

void GetCheeseColourFromDatabase(Cheese* cheese_ptr, int* colour_ptr);

Now what do you do?

// returns reference to local variable
const int& Cheese::GetColour() const
{
int colour;
GetCheeseColourFromDatabase(this, &colour);
return colour;
}

// don't try this on more than one cheese
const int& Cheese::GetColour() const
{
static int colour;
GetCheeseColourFromDatabase(this, &colour);
return colour;
}

// leaks memory
const int& Cheese::GetColour() const
{
int* colour = new int;
GetCheeseColourFromDatabase(this, colour);
return *colour;
}

Essentially by returning a reference you have committed yourself to storing
the cheese colour as an int in your object somewhere. Sometimes its good not
to make that commitment.

john
Jul 22 '05 #20

"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...
Richard Herring wrote:
What happens if you move to a more sophisticated colour model? Instead
of storing an int, maybe you need to compute something from the user's
choice, the available palette, the kind of display device etc...
No, you create a new or derived class.


But then you break everyone's code that uses your original object! They now
have to change their code to use your new object, whereas if you just
returned the computed value from the accessor, the user of your class never
even has to know how that value was computed, how it was stored, or
anything. They never even know the underlying accessor code was changed at
all. They get the value they want when they ask for it, and that's all they
should care about.

Experience has taught me this well. In writing database-access programs, I
often had to change something on the back end, and I was in general
*required* to not change the interface. When the user wants the trip
mileage, they never need to know if that was a stored value, or if it was
computed via a third-party mileage lookup. WIth thousands of users of our
system spread across the country, it was *very* important to make these kind
of changes as invisible to the users as possible. (It often took at least a
month to propogate changes to users when we had to make an interface change,
and we had to in effect maintain two system during such transitions...what a
pain!)
OK, add some functionality to compute it:

private:
int ComputeComplicatedColour(int userColour, palette p, display d)
const;

If returning a value, no problem; just change your access function to
this:
int GetColour() const
{ return ComputeComplicatedColour(colour, palette, device); }


You have now just changed the behavior of the original function with

respect to performance, which is a very real and tangible change.

Only in the internal behavior of the object, not in the interface or the
contract to provide the requested value.
This is why I advocate const reference member accessors to simple data -- it *guarantees* that access to the underlying data is immediate and absolute, and will stay that way. It doesn't break encapsulation as some have said, but
creates an immutable contract between the class designer and class user. You can't get that w/ functions.


I don't understand this. Why is a guarantee to "immediate and absolute"
access to the underlying data a requirement? What does the user of the
class care how the data is stored, represented, obtained or calculated? The
contract is to provide the value asked for, not (in general) a specification
of how that value is obtained or stored.

If you have some special requirement to actually see the data, as it is
stored (it that's even possible...sometimes you *have* to calculate it!),
then that's a totally separate need that's not part of the OP's question,
and only relevant to the question in that specific instance, not in general.

For "simple" data (e.g., the built-in types), it's also likely to be more
efficient to return by value than by reference. I'd personally be more
inclined to return by (const) reference something that had a significant
copy-construction overhead.

-Howard


Jul 22 '05 #21


I've read all your posts on this.

I would only use my const references method if there's an actual
variable/object within the class which I want to be read-only. In no other
place would I use it.
For example, a simple read-only instance counter:
#include <iostream>
class Human
{
private:

static unsigned long int prv_population_earth;

public:

static const unsigned long int& population_earth;

Human(void)
{
++prv_population_earth;
}

Human(Human&)
{
++prv_population_earth; //Cloning is a reality!
}

~Human(void)
{
--prv_population_earth;
}
};
unsigned long int Human::prv_population_earth = 0;
const unsigned long int& Human::population_earth =
Human::prv_population_earth;
int main(void)
{
std::cout << "Population of Earth: " << Human::population_earth;

//Human::population_earth += 5; //Compile error
}

Here's an obvious situation where the reference will always refer to a
proper variable/object which is a part of the class, whether it be static or
otherwise.
-JKop
Jul 22 '05 #22
>I don't understand your logic.

Let's say I change the int to a double .

A) MY CODE: Change the "const int&" to "const double&"

B) YOUR CODE: Change "int GetColour(void)" to "double GetColour(void)".
From my original post...

"So long as the data represented still conceptually represents an integer than
changes to the implementation need not have great impact."

With the above example you are doing more than changing the location and or
representation of your data. You are changing the meaning of "colour" for your
class.

Sometimes that may be necessary. If making "colour" an int was not the right
initial decision than you may very well have to change it to double when you
realize the original decision was wrong.

I would argue this goes beyond a mere implementation detail. How and where the
data is stored is an implementation detail. The type of the data as viewed by
users of the class, particularly for calling getters and setters, is part of
the abstraction/contract/interface/etc for the class.

Your example quoted here changes/violates that abstraction/contract etc...
To which code do you refer? My first one with member functions that return
const references, or my second one which has public const member references
which are initialized with private non-const variables?


All my thoughts were driven by your first solution.
Brian F. Seaberg
Naperville, Illinois
Delray Beach, Florida
Jul 22 '05 #23
Howard wrote:

"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...
Richard Herring wrote:
What happens if you move to a more sophisticated colour model? Instead
of storing an int, maybe you need to compute something from the user's
choice, the available palette, the kind of display device etc...
No, you create a new or derived class.


But then you break everyone's code that uses your original object! They now
have to change their code to use your new object, whereas if you just
returned the computed value from the accessor, the user of your class never
even has to know how that value was computed, how it was stored, or
anything. They never even know the underlying accessor code was changed at
all. They get the value they want when they ask for it, and that's all they
should care about.


??? Explain to me how you _break_ existing code by creating a new or derived
class. In every scenario that I've been involved in, creating a new/derived
class broke nothing -- and those that wanted the extended/different behavior
provided by the new class, modified their code.

Maybe they _should_ know that the accessor has changed, perhaps in subtle ways
that the modifying author didn't foresee...
Experience has taught me this well. In writing database-access programs, I
often had to change something on the back end, and I was in general
*required* to not change the interface. When the user wants the trip
mileage, they never need to know if that was a stored value, or if it was
computed via a third-party mileage lookup. WIth thousands of users of our
system spread across the country, it was *very* important to make these kind
of changes as invisible to the users as possible. (It often took at least a
month to propogate changes to users when we had to make an interface change,
and we had to in effect maintain two system during such transitions...what a
pain!)


Sure, there are many (most!) cases where a functional-based accessor is the
appropriate implementation -- but I'm not limiting myself to saying that it is
the _only_ way to implement accessors.
OK, add some functionality to compute it:

private:
int ComputeComplicatedColour(int userColour, palette p, display d)
const;

If returning a value, no problem; just change your access function to
this:
int GetColour() const
{ return ComputeComplicatedColour(colour, palette, device); }


You have now just changed the behavior of the original function with

respect to
performance, which is a very real and tangible change.


Only in the internal behavior of the object, not in the interface or the
contract to provide the requested value.


That is correct, but you are presuming that the only imposed requirements are
for the interface and returned value. There are other characteristics that
must be taken into account when implementing a public function, and one of
those are performance characteristics.
This is why I advocate const reference member accessors to simple data --

it
*guarantees* that access to the underlying data is immediate and absolute,

and
will stay that way. It doesn't break encapsulation as some have said, but
creates an immutable contract between the class designer and class user.

You
can't get that w/ functions.


I don't understand this. Why is a guarantee to "immediate and absolute"
access to the underlying data a requirement? What does the user of the
class care how the data is stored, represented, obtained or calculated? The
contract is to provide the value asked for, not (in general) a specification
of how that value is obtained or stored.


"Immediate and absolute" access is only a requirement if necessary, hardly an
absolute for all (most?) implementations.

In most cases, the user will not care how the data is stored, but they may care
how the data is accessed *or* computed.

Here is a simple example: suppose you are using a string class that implements
the length as a function (string::length()). Now, when iterating over that
string in a for-loop, they need to decide on:

size_t length = str.length();
for (int index=0; index<length; index++) // etc.

-- or --

for (int index=0; index<str.length(); index++) // etc.

If the implementation details of length() is unknown, they have to resort to
the first.

However, if the length is exposed as a public data reference, then it can be
guaranteed that str.length is immediate access and results in:

class string
{
public:
const size_t & length;
// etc.
};

for (int index=0; index<str.length; index++) // etc.

Finally, I'm not advocating this idiom in any particular case, just saying that
in the given situation, it may be appropriate and suitable. If you happen to
disagree, that is perfectly fine with me, I'm not trying to convince you
otherwise, I'm just leaving my coding options open.
Jul 22 '05 #24
In message <40***************@nospam.com>, Julie <ju***@nospam.com>
writes
Richard Herring wrote:
What happens if you move to a more sophisticated colour model? Instead
of storing an int, maybe you need to compute something from the user's
choice, the available palette, the kind of display device etc...
No, you create a new or derived class.


Why? The interface hasn't changed, this is just an improved
implementation. The client code doesn't need to be changed at all to
make use of it. It might not even need to be recompiled.
OK, add some functionality to compute it:

private:
int ComputeComplicatedColour(int userColour, palette p, display d)
const;

If returning a value, no problem; just change your access function to
this:
int GetColour() const
{ return ComputeComplicatedColour(colour, palette, device); }
You have now just changed the behavior of the original function with respect to
performance, which is a very real and tangible change.


The interface is unchanged. What do you mean by "performance" ? Can the
client code tell that anything has changed?
This is why I advocate const reference member accessors to simple data -- it
*guarantees* that access to the underlying data
*What* underlying data? The point here is that it might not even exist.
is immediate and absolute,
What is "unimmediate" or "unabsolute" about the value returned by a
function which returns by value?
and
will stay that way.
You mean that the designer is not at liberty to change something that's
part of the implementation, not the interface.
It doesn't break encapsulation as some have said,
It unnecessarily exposes implementation detail.
but
creates an immutable contract between the class designer and class user.
A contract that's unnecessarily restrictive of the designer.
You
can't get that w/ functions.


(Functions returning by value, I assume you mean.)

Indeed you don't, and a good thing too.

--
Richard Herring
Jul 22 '05 #25
JKop wrote:
Where then is the integer to initialize your reference going to come
from?


I don't understand your logic.

Let's say I change the int to a double .


Don't change it from int to double.
Change it from:
the int is a member of your class
to
the int value is looked up in a database

The reference needs some int variable to
return a reference. Where is this variable
located in case of lookup in database?

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #26
JKop wrote:

DaKoadMunky posted:
For accessors I prefer the return-by-value approach rather than the
return-by-reference approach.

The return-by-reference approach I believe creates an implementation
dependency.

In your case you are returning references to integers. This seems to
work out fine because you have chosen to store integers and thus have
integers with which to initialize your references.

What happens though if you decide you want to modify your class to
change how and/or where your data is stored?

Where then is the integer to initialize your reference going to come
from?


I don't understand your logic.

Let's say I change the int to a double .

A) MY CODE: Change the "const int&" to "const double&"

B) YOUR CODE: Change "int GetColour(void)" to "double GetColour(void)".

Karl mentioned something about this too, but I still don't see your
argument.


Another example:

Think of a class that handles circles.

class Circle
{
public:
Circle( double Radius ) : m_Radius( Radius ), m_Area ( PI * Radius * Radius ) {}

void SetRadius( double Radius ) { m_Radius = Radius; m_Area = PI * Radius * Radius; }

const double& Area() { return m_Radius; }

protected:
double m_Radius;
double m_Area;
};

The important thing is the member m_Area and how you return it in function Area().
I used your method.
The idea was: since calculating the area is a 'costly' operation and you expect
the rest of your program to use that area often, you compute the area as early
as possible and simply cache the result.

Now time goes by and you notice something stanga about your program: Area isn't
called nearly as often as you originally thought it would be. On the other hand
your program seems to take up a lot of memory and there are millions of Circle
objects around. So any way of conserving memory would be a good thing to do.
Well. Since function Area() isn't called that often, you could change your strategy:
instead of precomputing m_Area whenever you have a Radius and caching that, you
simply calculate the area when it is needed.
But you have 1 important thing: You are not allowed to change the function interface
in any way: all the function signatures have to stay the same!

Now your method of returning a reference turns into a bommerang. It is nearly
impossible to do that otherwise simple change of dropping the m_Area member
variable and mofing the calulation into function Area(). You simply don't have
a variable for returning a reference to it.

Now compare this to:

class Circle
{
public:
Circle( double Radius ) : m_Radius( Radius ), m_Area ( PI * Radius * Radius ) {}

void SetRadius( double Radius ) { m_Radius = Radius; m_Area = PI * Radius * Radius; }

double Area() { return m_Radius; }

protected:
double m_Radius;
double m_Area;
};

This is the original class with the Area() function as most of us would write
it. On any decent compiler it produces code which is no less efficient then
your return by reference version.

But now the modification is simple:

class Circle
{
public:
Circle( double Radius ) : m_Radius( Radius ) {}

void SetRadius( double Radius ) { m_Radius = Radius }

double Area() { return PI * Radius * Radius; }

protected:
double m_Radius;
};

All the function signatures stay the same. Only the internals of the
class have changed.

By returning a reference, you have exposed some information from
inside the class to the outside world: there is a double variable
or otherwise I would not be able to return a reference to it.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #27
Karl Heinz Buchegger posted:
JKop wrote:
> Where then is the integer to initialize your reference going to come
> from?


I don't understand your logic.

Let's say I change the int to a double .


Don't change it from int to double.
Change it from:
the int is a member of your class
to
the int value is looked up in a database

The reference needs some int variable to
return a reference. Where is this variable
located in case of lookup in database?


Each block of cheese has a colour. Yellow, white, or maybe even green. This
is a fundamental attribute of a block of cheese.

This is all, and only all, what my code does. Firstly, here was the original
way of working with it:

int main()
{
Cheese block;

TakesInt(block.colour);

//I've no problem at all with the above

block.colour = 4;

//I don't like colour changing cheese
}

And then with my code:

int main()
{
Cheese block;

TakesInt(block.colour);

block.colour = 4; // Compile ERROR
}

That's all I was ever ever ever ever talking about, a read-only member
variable. No more, no less, just a read-only member variable. I reiterate, a
read-only member variable.
-JKop
Jul 22 '05 #28
JKop wrote:

Karl Heinz Buchegger posted:
JKop wrote:

> Where then is the integer to initialize your reference going to come
> from?

I don't understand your logic.

Let's say I change the int to a double .
Don't change it from int to double.
Change it from:
the int is a member of your class
to
the int value is looked up in a database

The reference needs some int variable to
return a reference. Where is this variable
located in case of lookup in database?


Each block of cheese has a colour. Yellow, white, or maybe even green. This
is a fundamental attribute of a block of cheese.


I don't doubt that. But who says that that colour needs to be *stored*
in the Cheese object itself.

What you are saying is, in terms of C++
Every Cheese object needs to have a member function which returns
the colour.
That's ok, and I agree with that. But with what I don't agree is *how*
this function comes up with the value it returns. The value doesn't
need to be stored in the Cheese object itself.

This is all, and only all, what my code does. Firstly, here was the original
way of working with it:

int main()
{
Cheese block;

TakesInt(block.colour);

//I've no problem at all with the above

block.colour = 4;

//I don't like colour changing cheese
}

And then with my code:

int main()
{
Cheese block;

TakesInt(block.colour);

block.colour = 4; // Compile ERROR
}

That's all I was ever ever ever ever talking about, a read-only member
variable. No more, no less, just a read-only member variable. I reiterate, a
read-only member variable.


No problem with that. Your intention is clear.
The rest of the group is talking about, why this is not such a good
idea. To be precise: To have a read-only member would be a good idea.
The problem is, that it can't be implemented in C++ the way most of
us would like it to be. You have shown an implementation and we have
talked about why we are not happy with it.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #29
Karl Heinz Buchegger posted:
No problem with that. Your intention is clear.
The rest of the group is talking about, why this is not such a good
idea. To be precise: To have a read-only member would be a good idea.
The problem is, that it can't be implemented in C++ the way most of
us would like it to be. You have shown an implementation and we have
talked about why we are not happy with it.

Are you saying that a class should have no public member variables at all?
That's what it sounds like. In my example, there *is* a public member
variable, and it is read-only.
-JKOp
Jul 22 '05 #30
JKop wrote:

Karl Heinz Buchegger posted:
No problem with that. Your intention is clear.
The rest of the group is talking about, why this is not such a good
idea. To be precise: To have a read-only member would be a good idea.
The problem is, that it can't be implemented in C++ the way most of
us would like it to be. You have shown an implementation and we have
talked about why we are not happy with it.
Are you saying that a class should have no public member variables at all?


Yep.
Exposing public member variables always ties the code that uses your
class with the class internals. Thus you cannot change class internals
without breaking the code that uses it.
That's what it sounds like. In my example, there *is* a public member
variable, and it is read-only.

-JKOp

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #31
JKop posted:
#include <iostream>
class Human
{
private:

static unsigned long int prv_population_earth;

public:

static const unsigned long int& population_earth;

Human(void)
{
++prv_population_earth;
}

Human(Human&)
{
++prv_population_earth; //Cloning is a reality!
}

~Human(void)
{
--prv_population_earth;
}
};
unsigned long int Human::prv_population_earth = 0;
const unsigned long int& Human::population_earth =
Human::prv_population_earth;
int main(void)
{
std::cout << "Population of Earth: " << Human::population_earth;

//Human::population_earth += 5; //Compile error
}

Or alternatively, you can just declare it const and use const_cast in the
member functions. Come to think of it, that's why I'd prefer over using
const references!

-JKop
Jul 22 '05 #32

"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...
Howard wrote:

"Julie" <ju***@nospam.com> wrote in message
news:40***************@nospam.com...
Richard Herring wrote:
> What happens if you move to a more sophisticated colour model? Instead > of storing an int, maybe you need to compute something from the user's > choice, the available palette, the kind of display device etc...

No, you create a new or derived class.

But then you break everyone's code that uses your original object! They now
have to change their code to use your new object, whereas if you just
returned the computed value from the accessor, the user of your class never even has to know how that value was computed, how it was stored, or
anything. They never even know the underlying accessor code was changed at all. They get the value they want when they ask for it, and that's all they should care about.


??? Explain to me how you _break_ existing code by creating a new or

derived class. In every scenario that I've been involved in, creating a new/derived class broke nothing -- and those that wanted the extended/different behavior provided by the new class, modified their code.

Below, I did explain. As I said, my system was used by thousands across the
country, and if there was any back-end database change or access method
change, I was in general *required* to implement without changing the public
interfaces. This has nothing to do with providing some neat new toy they
can play with, but changing the way our classes do their work internally,
which is none of the user's business.

Sure, I had performance requirements to accomodate, but those drove how I
internally did my work. If it takes a month to propogate interface changes
out to the users, what good is that if it saves a few milliseconds of
functon call time? I had to make changes to the back end fairly frequently
(some of them required by the federal gov't), and there's no way we could
send out a whole round of software to the uers every time we changed how we
stored or accessed our data.
Maybe they _should_ know that the accessor has changed, perhaps in subtle ways that the modifying author didn't foresee...
Experience has taught me this well. In writing database-access programs, I often had to change something on the back end, and I was in general
*required* to not change the interface. When the user wants the trip
mileage, they never need to know if that was a stored value, or if it was computed via a third-party mileage lookup. WIth thousands of users of our system spread across the country, it was *very* important to make these kind of changes as invisible to the users as possible. (It often took at least a month to propogate changes to users when we had to make an interface change, and we had to in effect maintain two system during such transitions...what a pain!)
Sure, there are many (most!) cases where a functional-based accessor is

the appropriate implementation -- but I'm not limiting myself to saying that it is the _only_ way to implement accessors.

Ok, but your statement that started me off responding here was "No, you
create a new or derived class." And I'm suggesting that's not the common
way to change your internal implementation. The whole point of
encapsulation is that the internal workings are private, and not the
business of anyone using the object (unless otherwise specified explicitly,
such as specific side-effects).
> OK, add some functionality to compute it:
>
> private:
> int ComputeComplicatedColour(int userColour, palette p, display d)
> const;
>
> If returning a value, no problem; just change your access function to > this:
> int GetColour() const
> { return ComputeComplicatedColour(colour, palette, device); }

You have now just changed the behavior of the original function with

respect to
performance, which is a very real and tangible change.


Only in the internal behavior of the object, not in the interface or the
contract to provide the requested value.


That is correct, but you are presuming that the only imposed requirements

are for the interface and returned value. There are other characteristics that must be taken into account when implementing a public function, and one of
those are performance characteristics.

Sure, but that's a separate specification, not part of the contract provided
by the function interface. And in the case of something simple like
computing a color from some values, how much of a hit are we talking?
COmpare that to the month it took me to distribute code changes to the
users!
This is why I advocate const reference member accessors to simple data --
it
*guarantees* that access to the underlying data is immediate and
absolute, and
will stay that way. It doesn't break encapsulation as some have said,
but creates an immutable contract between the class designer and class

user. You
can't get that w/ functions.


I don't understand this. Why is a guarantee to "immediate and absolute"
access to the underlying data a requirement? What does the user of the
class care how the data is stored, represented, obtained or calculated? The contract is to provide the value asked for, not (in general) a specification of how that value is obtained or stored.


"Immediate and absolute" access is only a requirement if necessary, hardly

an absolute for all (most?) implementations.

In most cases, the user will not care how the data is stored, but they may care how the data is accessed *or* computed.

Here is a simple example: suppose you are using a string class that implements the length as a function (string::length()). Now, when iterating over that string in a for-loop, they need to decide on:

size_t length = str.length();
for (int index=0; index<length; index++) // etc.

-- or --

for (int index=0; index<str.length(); index++) // etc.

If the implementation details of length() is unknown, they have to resort to the first.

However, if the length is exposed as a public data reference, then it can be guaranteed that str.length is immediate access and results in:

class string
{
public:
const size_t & length;
// etc.
};

for (int index=0; index<str.length; index++) // etc.

Profiling can tell you if performance is suffering, and some published
knowledge about internals can indeed tell you if you can do something
better. But if you're *depending* upon the internal implementation details
of a class you use in order to design how you use the class, then you most
definitely *are* breaking encapsulation. That's exactly what encapsulation
is about, keeping those internals private. (Look at most third-party
libraries...you get a .dll or .lib or some other binary of the actual
implementation code, and only header files as source code. They don't
*want* you to know their internal workings! It's probably copyrighted, for
that matter.)
Finally, I'm not advocating this idiom in any particular case, just saying that in the given situation, it may be appropriate and suitable. If you happen to disagree, that is perfectly fine with me, I'm not trying to convince you
otherwise, I'm just leaving my coding options open.


Ok, I can understand that. It's a "good thing" to look carefully at the
specific problem at hand before making decisions as to how to solve it.

But I still say it's better, in general, for accessors to return by value
than by reference. (And I also agree with others that, even in the specific
case given, it's better, because it's always possible that the object that
returned the reference could be destroyed while the calling code still
wanted to use that value.)

-Howard



Jul 22 '05 #33
JKop <NU**@NULL.NULL> wrote in news:lY*****************@news.indigo.ie:
Or alternatively, you can just declare it const and use const_cast in
the member functions. Come to think of it, that's why I'd prefer over
using const references!


Um, no (the const_cast idea). If you declare it const, and then attempt to
modify it via a const_cast, you have entered the realm of Undefined
Behaviour. Theoretically I can dream up a computer where one could mark an
arbitrary range of memory addresses as read-only. On this computer, the
compiler is perfectly within it's rights to mark the memory where that
member is as read-only. Then when you try to write to that memory area,
the CPU traps and your program blows up. const_cast is for interfacing
with legacy code where the function declarations aren't const-correct, but
the actual code behaves as if the consts were there anyway.
Jul 22 '05 #34
Andre Kostur posted:
JKop <NU**@NULL.NULL> wrote in news:lY*****************@news.indigo.ie:
Or alternatively, you can just declare it const and use const_cast in
the member functions. Come to think of it, that's why I'd prefer over
using const references!


Um, no (the const_cast idea). If you declare it const, and then
attempt to modify it via a const_cast, you have entered the realm of
Undefined Behaviour. Theoretically I can dream up a computer where one
could mark an arbitrary range of memory addresses as read-only. On
this computer, the compiler is perfectly within it's rights to mark the
memory where that member is as read-only. Then when you try to write
to that memory area, the CPU traps and your program blows up.
const_cast is for interfacing with legacy code where the function
declarations aren't const-correct, but the actual code behaves as if
the consts were there anyway.

If some-one was brilliant enough to devise such a system, I believe that
they would be compentant enough to know of the well documented const_cast
operator. To ignore const_cast would be a fault.
-JKop
Jul 22 '05 #35
Howard posted:
But I still say it's better, in general, for accessors to return by
value than by reference. (And I also agree with others that, even in
the specific case given, it's better, because it's always possible that
the object that returned the reference could be destroyed while the
calling code still wanted to use that value.)

-Howard

Just as some-one with similar intelligence could:
SomeClass* p_some_class = new SomeClass;

//Time goes by

delete p_some_class;

//Time goes by

p_some_class->DoStuff();
-JKop
Jul 22 '05 #36
JKop <NU**@NULL.NULL> wrote in news:nV*****************@news.indigo.ie:
Andre Kostur posted:
JKop <NU**@NULL.NULL> wrote in
news:lY*****************@news.indigo.ie:
Or alternatively, you can just declare it const and use const_cast
in the member functions. Come to think of it, that's why I'd prefer
over using const references!


Um, no (the const_cast idea). If you declare it const, and then
attempt to modify it via a const_cast, you have entered the realm of
Undefined Behaviour. Theoretically I can dream up a computer where
one could mark an arbitrary range of memory addresses as read-only.
On this computer, the compiler is perfectly within it's rights to
mark the memory where that member is as read-only. Then when you try
to write to that memory area, the CPU traps and your program blows
up. const_cast is for interfacing with legacy code where the function
declarations aren't const-correct, but the actual code behaves as if
the consts were there anyway.

If some-one was brilliant enough to devise such a system, I believe
that they would be compentant enough to know of the well documented
const_cast operator. To ignore const_cast would be a fault.


Not from the Standard point of view. The Standard states that attempting
to modify a const object via a const cast is undefined behaviour. End of
story.

Jul 22 '05 #37
Andre Kostur posted:
Not from the Standard point of view. The Standard states that
attempting to modify a const object via a const cast is undefined
behaviour. End of story.


What is the function, the purpose, of const_cast? It's essentially for
editing a const object. If this is undefined behaviour, they operator should
be renamed to:

const_cast_undefined_behaviour
-JKop
Jul 22 '05 #38
JKop wrote:

Andre Kostur posted:
Not from the Standard point of view. The Standard states that
attempting to modify a const object via a const cast is undefined
behaviour. End of story.


What is the function, the purpose, of const_cast?


As Andrea has already pointed out:

To allow for interfacing with legacy code, which, for whatever
reasons, is not const correct and you can't change that code.

--
Karl Heinz Buchegger
kb******@gascad.at
Jul 22 '05 #39
JKop <NU**@NULL.NULL> wrote:
Not from the Standard point of view. The Standard states that
attempting to modify a const object via a const cast is undefined
behaviour. End of story.


What is the function, the purpose, of const_cast? It's essentially for
editing a const object. If this is undefined behaviour, they operator should
be renamed to:

const_cast_undefined_behaviour


It's not undefined behaviour to use const_cast.
It's undefined behaviour to modify a constant object (whether
it be via a const_cast, or any other method).

There is no UB here:

int x;
int const &y = x;
const_cast<int &>(y) = 1;

(BTW this is another reason that your idea of having const reference
members instead of 'get functions' is bad: anyone can just const_cast
and modify the original, whereas with 'get functions' it's much
harder to modify the original.)
Jul 22 '05 #40

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

2
by: Gunnar | last post by:
Hello, I've just written a CPP program that reads integers from a binary file, and used this code while (my_ifstram.read( (char* ) &number, sizeof(int)) { // do something with number } My...
6
by: Steve | last post by:
Hi, I'm trying to convert a file reading loop into one using streams. The BSD OS read API returns the number of bytes read, but istream::read returns itself. How can I find out the number of...
12
by: Steven T. Hatton | last post by:
I know of a least one person who believes std::ifstream::read() and std::ofstream::write() are "mistakes". They seem to do the job I want done. What's wrong with them. This is the code I...
2
by: Sandman | last post by:
Just looking for suggestion on how to do this in my Web application. The goal is to keep track of what a user has and hasn't read and present him or her with new material I am currently doing...
2
by: Andrea Bauer | last post by:
Hallo, wie kann ich so eine Datei unter .Net schreiben C++ oder C#. Bitte mit Funktionsaufrufen. Vielen Dank. Grüße Andrea <Product> <ProgramNumber>2</ProgramNumber>
4
by: Ollie Cook | last post by:
Hi, I am having some difficulty with read(2) and interrupting signals. I expect I am misunderstanding how the two work together, so would appreciate some guidance. I am trying to 'time out' a...
1
by: Jose Reckoner | last post by:
I'm running python 2.3 on Windows XP. Anyone have a quick small script to convert .DT1 and .DEM data to ASCII or some other format? I don't need a viewer. Thanks!
0
by: phplasma | last post by:
Hey, I am currently attempting to implement a multi-threaded C# socket, using SSL (.pem file/certification/private key combo) server using Visual Studio C# Express. I have successfully made...
4
by: zl2k | last post by:
hi, there I have a appendable binary file of complex data structure named data.bin created by myself. It is written in the following format: number of Data, Data array Suppose I have...
5
by: Thomas Christensen | last post by:
This issue has been raised a couple of times I am sure. But I have yet to find a satisfying answer. I am reading from a subprocess and this subprocess sometimes hang, in which case a call to...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: ryjfgjl | last post by:
In our work, we often need to import Excel data into databases (such as MySQL, SQL Server, Oracle) for data analysis and processing. Usually, we use database tools like Navicat or the Excel import...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.