Quote:
Not quite sure what you mean by this, can you elaborate? If it's not a reference then you cant access bad memory like your example
Yes, you can. My example does so. Note that the
member to which a reference is being created (bar) is not itself a reference. The portion of your post I was replying to ("You have to initialize const &, making them not often useful as class members,") implied to me that you thought the
member needed to be a reference -- but it doesn't. You simply have to
create a reference to a member, and then cause that member to go away somehow. Then you have a reference that refers to invalid memory.
A reference (except in the case of a reference to a temporary, which this is not) does not "pin" the object it references and keep it alive in any way.
Quote:
If someone were to try to hold on to a reference for longer than the objects duration they would either need to write a bad block of code, as per your example,
The problem is that, while the code that I wrote is "bad," it's not really obviously so. Well, it's not
that obvious, at least. And when it occurs in production code, it is even less obvious.
Quote:
I really don't like these sort of comments. x is bad design, singletons, accessors/modifiers, globals, goto, etc.
Note that I didn't make any such blanket statement. I said (and specifically emphasized) that it
tends to do so, which is much less of a generalization than "it
is bad design;" it admits the possibility that there is a valid use for it.
Quote:How exactly does it break encapsulation? Because you can safely assume the position is a vec3 member if it returns a const & ? What difference does that make?
To some extent, yes, you can make that assumption and that is a minor encapsulation violation. That isn't a huge deal, though, because after all you could just look at the header; that's only a literal break of encapsulation. The bigger issue regarding encapsulation breakage is that it means that fundamental changes to the internals of the member in question
might cause breaking changes to the public interface. Remember, the public interface of a class is the hardest thing to change, so its very important to get it right (or as close as you can to right) the first time.
I mentioned this briefly already, but I'll expand on it. Consider a situation in which we return a reference to a internal field. Though it appears benign, in permitting this in our interface we have restricted our set of legal implementations to those that cache the value of that field somehow. If we ever need to change the implementation of the class to calculate that field's value on demand (perhaps because we have very tight memory restrictions, an equally valid possibility in any context where "return-by-reference-rather-than-value" provides signifigant performance gains), we can't. That value
must be stored or cached
somewhere (otherwise we'd have to return a reference to the temporary calculated value, obviously a problem), or we have to break the interface.
Admittedly, this is
somewhat less of a concern for hobbyist or amateur developers who might not have the burden of massive amounts of legacy code that would be adversly affected by a breaking interface change.
It also alleviated somewhat by returning a const reference, since changing the interface to return by value will silently work properly in a good deal of cases -- but not neccessarily all.
And I don't believe being a hobbyist is an excuse for making poor design choices.
Quote:
Sure, but fabricating some example that is dangerous isn't very productive either, and the chances that it will come up are pretty low in my experience. Most programmers know better
Holding the reference happens frequently. My example is trivial in the interest of illustration; in practice the site that causes the reference to become invalidated (the "delete") is usually far from the site at which the reference was acquired, buried behind a few levels of function calls. It doesn't happen because the programmer is stupid or doesn't know better, it happens
by accident because the API was easy to use incorrectly.
Quote:
At what overhead cost to the object? Sounds like an overengineered solution to an insignificant problem.
Copy-on-write isn't that hard to implement, and can pay dividends in areas other than returning by value from accessors. It was done, and rather quickly, for a number of objects on projects I've worked on. But yes, in general it is an insignifigant problem -- so it's often better to do it the safer way.
Quote:
"const" simply means I won't change it. It says nothing about someone else not changing it.
I know; that's what I was getting at. I read "they" in DrEvil's post as the implementor of the class's interface, so "they" would make the return const if "they" didn't want "I" (me) to change it. If "they" want me to change it (through that returned reference), const is not appropriate.