non-const reference and const reference

Discussion in 'C++' started by George2, Dec 15, 2007.

  1. George2

    George2 Guest

    Hello everyone,


    This is my understanding of non-const reference, const reference and
    their relationships with lvalue/rvalue. Please help to review whether
    it is correct and feel free to correct me. Thanks.

    1. A const reference can be binded to a rvalue, for example, a
    temporary object. And the "life" of the temporary object is guaranteed
    to be extended and we can safely operate through the const-reference.

    2. A non-const reference can not binded to a rvalue, I think the
    reason is rvalue is not addressable? And we can not change the rvalue
    through its reference? Are there any other reasons? I am not quite
    sure whether my understanding is fully correct. Since there are some
    non-modifiable lvalues (so we do not always need to modify values
    through its reference). I am still studying what is the reason in
    essence in compiler why a non-const reference can not be binded to a
    rvalue.

    3. Both const and non-const reference can be binded to a lvalue.


    thanks in advance,
    George
     
    George2, Dec 15, 2007
    #1
    1. Advertising

  2. * George2:
    > Hello everyone,
    >
    >
    > This is my understanding of non-const reference, const reference and
    > their relationships with lvalue/rvalue. Please help to review whether
    > it is correct and feel free to correct me. Thanks.
    >
    > 1. A const reference can be binded to a rvalue, for example, a
    > temporary object. And the "life" of the temporary object is guaranteed
    > to be extended and we can safely operate through the const-reference.


    Not quite.

    Lifetime extension of temporary happens when the reference is declared
    in local scope.

    It does not happen when you return a reference from a function.



    > 2. A non-const reference can not binded to a rvalue, I think the
    > reason is rvalue is not addressable?


    No, an rvalue can have an address. In particular, you can call member
    function on class type rvalues, and you can bind the rvalue to a
    reference to const. But note that "rvalue" refers to syntax, how you
    denote an object: it's not a property of the object so denoted.


    > And we can not change the rvalue
    > through its reference? Are there any other reasons?


    Consider

    void increment( unsigned& x ) { ++x; }

    int main() { int y = 0; increment( unsigned(y) ); }

    The cast produces an rvalue. If this compiled it would presumably
    increment a temporary instead of y.

    Bottom line is by disallowing that binding one avoids many pitfalls.


    > I am not quite
    > sure whether my understanding is fully correct. Since there are some
    > non-modifiable lvalues (so we do not always need to modify values
    > through its reference). I am still studying what is the reason in
    > essence in compiler why a non-const reference can not be binded to a
    > rvalue.
    >
    > 3. Both const and non-const reference can be binded to a lvalue.


    Yes.

    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Dec 15, 2007
    #2
    1. Advertising

  3. George2

    James Kanze Guest

    On Dec 15, 6:33 am, "Alf P. Steinbach" <> wrote:
    > * George2:


    > > This is my understanding of non-const reference, const reference and
    > > their relationships with lvalue/rvalue. Please help to review whether
    > > it is correct and feel free to correct me. Thanks.


    > > 1. A const reference can be binded to a rvalue, for example, a
    > > temporary object. And the "life" of the temporary object is guaranteed
    > > to be extended and we can safely operate through the const-reference.


    > Not quite.


    > Lifetime extension of temporary happens when the reference is
    > declared in local scope.


    Not at all. There are exactly three cases where the temporary
    has a different lifetime than the reference: when the reference
    is a class member (in that case, lifetime of the temporary is
    extended to match the lifetime of the entire constructor, but of
    course, the reference itself has the same lifetime as the
    constructed object); when the reference is a function argument
    (in which case, the temporary naturally has a longer lifetime
    than the reference to begin with), and when the reference is a
    return value (the temporary only persists until the function
    exits).

    On the other hand, there's certainly no restriction to local
    scope; the lifetime is extended in all other cases.

    The usual problem that people have is that the lifetime isn't
    extended when a temporary is bound to a reference; the compiler
    can't even know, in the general case, if what it is binding is a
    temporary. The lifetime is extended when the reference is
    *initialized* with a temporary. The difference is a bit subtle;
    what it comes down to is that the lifetime is extended *only*
    when the initialization expression is a temporary; not when it
    is another reference (which might be bound to a temporary). The
    best way to think of it in practice, I find, is to consider that
    the extension of the lifetime isn't transitive.

    > It does not happen when you return a reference from a function.


    Nor when you initialize a member. On the other hand, it applies
    to global references just as much as to local ones.

    [...]
    > Consider


    > void increment( unsigned& x ) { ++x; }


    > int main() { int y = 0; increment( unsigned(y) ); }


    > The cast produces an rvalue. If this compiled it would presumably
    > increment a temporary instead of y.


    Not "If this compiled", but "When it was legal C++ and
    compiled". The earliest versions of C++ (up to about 1988, I
    think) allowed this, with exactly the semantics you suggest.
    The restriction was introduced exactly because the rule was so
    error prone.

    --
    James Kanze (GABI Software) email:
    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
     
    James Kanze, Dec 15, 2007
    #3
  4. * James Kanze:
    > On Dec 15, 6:33 am, "Alf P. Steinbach" <> wrote:
    >> * George2:

    >
    >>> This is my understanding of non-const reference, const reference and
    >>> their relationships with lvalue/rvalue. Please help to review whether
    >>> it is correct and feel free to correct me. Thanks.

    >
    >>> 1. A const reference can be binded to a rvalue, for example, a
    >>> temporary object. And the "life" of the temporary object is guaranteed
    >>> to be extended and we can safely operate through the const-reference.

    >
    >> Not quite.

    >
    >> Lifetime extension of temporary happens when the reference is
    >> declared in local scope.

    >
    > Not at all. There are exactly three cases where the temporary
    > has a different lifetime than the reference: when the reference
    > is a class member (in that case, lifetime of the temporary is
    > extended to match the lifetime of the entire constructor, but of
    > course, the reference itself has the same lifetime as the
    > constructed object); when the reference is a function argument
    > (in which case, the temporary naturally has a longer lifetime
    > than the reference to begin with), and when the reference is a
    > return value (the temporary only persists until the function
    > exits).


    I hear you say "not at all", then failing to give any counter-example.


    > On the other hand, there's certainly no restriction to local
    > scope


    That's true.


    >; the lifetime is extended in all other cases.


    Sorry, that's false. You pointed out three cases above, yourself.



    [snip]
    >
    >> It does not happen when you return a reference from a function.

    >
    > Nor when you initialize a member. On the other hand, it applies
    > to global references just as much as to local ones.


    That's true.


    > [...]
    >> Consider

    >
    >> void increment( unsigned& x ) { ++x; }

    >
    >> int main() { int y = 0; increment( unsigned(y) ); }

    >
    >> The cast produces an rvalue. If this compiled it would presumably
    >> increment a temporary instead of y.

    >
    > Not "If this compiled", but "When it was legal C++ and
    > compiled".


    Sorry, that's bull. It makes no sense to talk about "valid" (or
    "legal") C++ before standardization.


    > The earliest versions of C++ (up to about 1988, I
    > think) allowed this, with exactly the semantics you suggest.
    > The restriction was introduced exactly because the rule was so
    > error prone.


    In this group we discuss the C++ language.

    But yes, it would probably have been even better if I'd expressed the
    rules in terms of initialization rather than two examples.


    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Dec 15, 2007
    #4
  5. George2

    James Kanze Guest

    On Dec 15, 11:38 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:
    > > On Dec 15, 6:33 am, "Alf P. Steinbach" <> wrote:


    [...]
    > >>> 1. A const reference can be binded to a rvalue, for
    > >>> example, a temporary object. And the "life" of the
    > >>> temporary object is guaranteed to be extended and we can
    > >>> safely operate through the const-reference.


    > >> Not quite.


    > >> Lifetime extension of temporary happens when the reference
    > >> is declared in local scope.


    > > Not at all. There are exactly three cases where the
    > > temporary has a different lifetime than the reference: when
    > > the reference is a class member (in that case, lifetime of
    > > the temporary is extended to match the lifetime of the
    > > entire constructor, but of course, the reference itself has
    > > the same lifetime as the constructed object); when the
    > > reference is a function argument (in which case, the
    > > temporary naturally has a longer lifetime than the reference
    > > to begin with), and when the reference is a return value
    > > (the temporary only persists until the function exits).


    > I hear you say "not at all", then failing to give any
    > counter-example.


    In the context above, your statement "declared in local scope"
    implies, not elsewhere. That may not be what you meant, but it
    sure sounded like it.

    > > On the other hand, there's certainly no restriction to local
    > > scope


    > That's true.


    > >; the lifetime is extended in all other cases.


    > Sorry, that's false. You pointed out three cases above, yourself.


    Exactly. All other cases than the ones I mentionned.

    > [snip]


    > >> It does not happen when you return a reference from a function.


    > > Nor when you initialize a member. On the other hand, it applies
    > > to global references just as much as to local ones.


    > That's true.
    >
    > > [...]
    > >> Consider


    > >> void increment( unsigned& x ) { ++x; }


    > >> int main() { int y = 0; increment( unsigned(y) ); }


    > >> The cast produces an rvalue. If this compiled it would presumably
    > >> increment a temporary instead of y.


    > > Not "If this compiled", but "When it was legal C++ and
    > > compiled".


    > Sorry, that's bull. It makes no sense to talk about "valid"
    > (or "legal") C++ before standardization.


    You're either being intentionally obtuse, or just playing
    stupid. So what was the language in which I wrote valid and
    legal programs between 1991 (when I first started working
    intensively in C++) and 1998 (when the standard was adopted).

    The standardization committee didn't invent the word
    C++.

    In this case, it's worth pointing out that the original language
    did allow initializing a non-const reference with a temporary.
    The rule was changed as a result of concrete experience.

    > > The earliest versions of C++ (up to about 1988, I think)
    > > allowed this, with exactly the semantics you suggest. The
    > > restriction was introduced exactly because the rule was so
    > > error prone.


    > In this group we discuss the C++ language.


    Which has existed since at least 1986 (the publication date of
    The C++ Programming Language).

    > But yes, it would probably have been even better if I'd
    > expressed the rules in terms of initialization rather than two
    > examples.


    The key problem I've seen in practice is that people seem to
    think that a temporary will last as long as any reference is
    bound to it. I personally find that it becomes clearer if the
    explination is couched in terms of what happens with the
    temporary: if the temporary is used to initialize a reference,
    it's lifetime is extended to that of that reference. The point
    of view is what happens to the temporary, and not what the
    reference was initialized with.

    Alternatively, some people seem to understand it better if I
    simply state that the extension of lifetime is not transitive;
    the fact that reference B is bound to reference A is bound to a
    temporary doesn't mean that reference B's lifetime affects the
    lifetime of the temporary.

    I have no real theories as to why one explination works better
    for some people, and the other one for others. Except that
    people are different.

    --
    James Kanze (GABI Software) email:
    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
     
    James Kanze, Dec 16, 2007
    #5
  6. * James Kanze:
    > On Dec 15, 11:38 pm, "Alf P. Steinbach" <> wrote:
    >> * James Kanze:
    >>> On Dec 15, 6:33 am, "Alf P. Steinbach" <> wrote:

    >
    > [...]
    >>>>> 1. A const reference can be binded to a rvalue, for
    >>>>> example, a temporary object. And the "life" of the
    >>>>> temporary object is guaranteed to be extended and we can
    >>>>> safely operate through the const-reference.

    >
    >>>> Not quite.

    >
    >>>> Lifetime extension of temporary happens when the reference
    >>>> is declared in local scope.

    >
    >>> Not at all. There are exactly three cases where the
    >>> temporary has a different lifetime than the reference: when
    >>> the reference is a class member (in that case, lifetime of
    >>> the temporary is extended to match the lifetime of the
    >>> entire constructor, but of course, the reference itself has
    >>> the same lifetime as the constructed object); when the
    >>> reference is a function argument (in which case, the
    >>> temporary naturally has a longer lifetime than the reference
    >>> to begin with), and when the reference is a return value
    >>> (the temporary only persists until the function exits).

    >
    >> I hear you say "not at all", then failing to give any
    >> counter-example.

    >
    > In the context above, your statement "declared in local scope"
    > implies, not elsewhere. That may not be what you meant, but it
    > sure sounded like it.
    >
    >>> On the other hand, there's certainly no restriction to local
    >>> scope

    >
    >> That's true.

    >
    >>> ; the lifetime is extended in all other cases.

    >
    >> Sorry, that's false. You pointed out three cases above, yourself.

    >
    > Exactly. All other cases than the ones I mentionned.
    >
    >> [snip]

    >
    >>>> It does not happen when you return a reference from a function.

    >
    >>> Nor when you initialize a member. On the other hand, it applies
    >>> to global references just as much as to local ones.

    >
    >> That's true.
    >>
    >>> [...]
    >>>> Consider

    >
    >>>> void increment( unsigned& x ) { ++x; }

    >
    >>>> int main() { int y = 0; increment( unsigned(y) ); }

    >
    >>>> The cast produces an rvalue. If this compiled it would presumably
    >>>> increment a temporary instead of y.

    >
    >>> Not "If this compiled", but "When it was legal C++ and
    >>> compiled".

    >
    >> Sorry, that's bull. It makes no sense to talk about "valid"
    >> (or "legal") C++ before standardization.

    >
    > You're either being intentionally obtuse, or just playing
    > stupid.


    Are you really sure you want to go that road, James?

    First posting a meaningless looks-like-a-clarification, then calling
    names when you're taken up on it?


    > So what was the language in which I wrote valid and
    > legal programs between 1991 (when I first started working
    > intensively in C++) and 1998 (when the standard was adopted).


    Assuming you used more than one compiler or one compiler with more than
    one set of options, the languages you used were not standard C++, and
    they were not one language:

    they were a number of slightly different languages, conforming in
    general to Bjarne Stroustup's "reference manual" for C++.

    By (May) 1991 that reference manual had already made the change we're
    discussing here.

    Programs using the earlier bind-temporary-to-reference-to-non-const
    could still compile and in that sense be valid (for a given compiler),
    for the intention was to "fade out" use of that feature. So your C++
    programs written between 1991 and 1998 could get away with being valid
    for the compiler(s) used, but invalid wrt. the "reference manual", and
    neither valid nor invalid wrt. to any standard, not yet existing.

    Interestingly, while the ARM cites the same rationale as I did earlier
    for disallowing the non-const ref binding to temporary, in one Usenet
    discussion I had with Bjarne Stroustrup about this, he cited his sense
    of elegance and unified rules for allowing temporary lifetime extension,
    just one rule fit all (and in particular also fitting argument passing).

    So I think there were a number of factors influencing the decision.


    > The standardization committee didn't invent the word
    > C++.
    >
    > In this case, it's worth pointing out that the original language
    > did allow initializing a non-const reference with a temporary.
    > The rule was changed as a result of concrete experience.


    Yes, it is a good example.


    >>> The earliest versions of C++ (up to about 1988, I think)
    >>> allowed this, with exactly the semantics you suggest. The
    >>> restriction was introduced exactly because the rule was so
    >>> error prone.

    >
    >> In this group we discuss the C++ language.

    >
    > Which has existed since at least 1986 (the publication date of
    > The C++ Programming Language).
    >
    >> But yes, it would probably have been even better if I'd
    >> expressed the rules in terms of initialization rather than two
    >> examples.

    >
    > The key problem I've seen in practice is that people seem to
    > think that a temporary will last as long as any reference is
    > bound to it. I personally find that it becomes clearer if the
    > explination is couched in terms of what happens with the
    > temporary: if the temporary is used to initialize a reference,
    > it's lifetime is extended to that of that reference.


    Sorry, that's not the case, as you have yourself pointed out earlier.


    > The point
    > of view is what happens to the temporary, and not what the
    > reference was initialized with.
    >
    > Alternatively, some people seem to understand it better if I
    > simply state that the extension of lifetime is not transitive;
    > the fact that reference B is bound to reference A is bound to a
    > temporary doesn't mean that reference B's lifetime affects the
    > lifetime of the temporary.
    >
    > I have no real theories as to why one explination works better
    > for some people, and the other one for others. Except that
    > people are different.


    I think concrete examples work best, as foundation for later
    generalization, and/or as clarification of an initial general statement.

    At least for this subject there aren't that many really different cases,
    so I think examples work fine, but the general rules get hairy --
    especially if we get into the rules about copy constructor availability,
    current and future.

    Cheers, & hth.,

    - Alf


    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Dec 16, 2007
    #6
  7. George2

    James Kanze Guest

    On Dec 16, 2:49 am, "Alf P. Steinbach" <> wrote:
    > * James Kanze:
    > >> [snip]


    > >>>> It does not happen when you return a reference from a function.


    > >>> Nor when you initialize a member. On the other hand, it applies
    > >>> to global references just as much as to local ones.


    > >> That's true.


    > >>> [...]
    > >>>> Consider


    > >>>> void increment( unsigned& x ) { ++x; }


    > >>>> int main() { int y = 0; increment( unsigned(y) ); }


    > >>>> The cast produces an rvalue. If this compiled it would presumably
    > >>>> increment a temporary instead of y.


    > >>> Not "If this compiled", but "When it was legal C++ and
    > >>> compiled".


    > >> Sorry, that's bull. It makes no sense to talk about "valid"
    > >> (or "legal") C++ before standardization.


    > > You're either being intentionally obtuse, or just playing
    > > stupid.


    > Are you really sure you want to go that road, James?


    > First posting a meaningless looks-like-a-clarification, then calling
    > names when you're taken up on it?


    First, I don't think the clarification was meaningless, because
    I've consistently encountered people who misunderstood the issue
    when it was presented in that way. And second, the attack is
    less ad hominim than a constatation concerning one particular
    statement, or way of reasoning. You statement "It makes no
    sense to talk about "valid" (or "legal") C++ before
    standardization" is simply ridiculous, and I know you know
    better. So I have to suppose that you're making it for some
    sort of rhetorical reason: being intentionally obtuse, playing
    stupid (since I know you're not), or trying to provoke some sort
    of reaction I can't see.

    > > So what was the language in which I wrote valid and
    > > legal programs between 1991 (when I first started working
    > > intensively in C++) and 1998 (when the standard was adopted).


    > Assuming you used more than one compiler or one compiler with
    > more than one set of options, the languages you used were not
    > standard C++, and they were not one language:


    > they were a number of slightly different languages, conforming in
    > general to Bjarne Stroustup's "reference manual" for C++.


    I was there, and the ARM was taken very much as a "standard".
    And with the exception of g++ (which really was a different
    language at the time), conformance was generally better than
    conformance to the ISO standard today. (Note that the chapters
    in the ARM on templates and exceptions were considered more or
    less experimental, and were not treated as part of the de facto
    standard.)

    > By (May) 1991 that reference manual had already made the
    > change we're discussing here.


    Become a standard? Again, I was there, and there was no ISO
    standard until 1998. And the text that would be the standard
    didn't really stabilize until 1996-1997. Until well after the
    1998, most users considered the ARM as the reference, not the
    ISO standard, simply because most compilers implemented
    something much closer to the ARM than to the ISO standard.

    > Programs using the earlier
    > bind-temporary-to-reference-to-non-const could still compile
    > and in that sense be valid (for a given compiler), for the
    > intention was to "fade out" use of that feature.


    In 1991, yes. The rule was changed before the ARM, and by 1991,
    the ARM was rapidly becoming the definition of what was legal
    and valid C++. The rule wasn't present in earlier versions of
    "The C++ Programming Language", however, which was the reference
    before the ARM.

    > So your C++ programs written between 1991 and 1998 could get
    > away with being valid for the compiler(s) used, but invalid
    > wrt. the "reference manual", and neither valid nor invalid
    > wrt. to any standard, not yet existing.


    A program which bound a temporary to a non-const reference
    wasn't valid or legal in 1991. And all of the "up to date"
    compilers at the time warned (except maybe g++: at the time, g++
    was so bad you couldn't use it). But I'm not sure what your
    point is. There was a standard. I evolved over time, some
    compilers took more time than others to update, and most treated
    the new restrictions as warnings, rather than errors, to avoid
    breaking existing code. The situation hasn't really changed,
    except that instead of Stroustrup himself promulgating the
    standard, it is defined by ISO.

    The definition of what is "valid" and "legal" C++ evolves over
    time.

    Look. I posted because, from experience, I know that the
    overall issue needs more clarification than you gave. Everytime
    someone hears that "if a temporary is bound to a reference, it's
    lifetime is extended to that of the reference", they seem to
    assume transitivity (which, strictly speaking, is implied in the
    statement, even if it wouldn't occur to me to assume it).

    At the end of the statement, I made a minor, unimportant
    correction, more in fun than anything else. (Maybe I should
    have put a smiley on it.) Technically, it's not "if it
    compiles" (since it doesn't), but "when it compiled" (since it
    once did). And you come back with this bullshit that there was
    no C++ language before ISO. Which, quite frankly, sort of
    surprises someone like me who was using it back then; who was
    writing C++ code, and sending in error reports to the compiler
    vendors for non-conformance with the language specification:
    "legal" and "valid" C++ code which didn't compile, or compiled,
    but did the wrong thing, and C++ code which should not have
    compiled, but did. Of course, we had to contend with the fact
    that not all compilers implemented all of the latest
    specification (but that's the case today as well), and that some
    compilers intentionally deviated in certain cases (also the case
    today).

    > Interestingly, while the ARM cites the same rationale as I did
    > earlier for disallowing the non-const ref binding to
    > temporary, in one Usenet discussion I had with Bjarne
    > Stroustrup about this, he cited his sense of elegance and
    > unified rules for allowing temporary lifetime extension, just
    > one rule fit all (and in particular also fitting argument
    > passing).


    > So I think there were a number of factors influencing the decision.


    As I said, the reason you cited was the reason I'd always heard.
    The example you gave is, in fact, the usual example I've seen.
    I'm quite convinced that it is the explination of why the change
    was made. My critical comment above is limited to your
    statement that you couldn't talk about "legal" and "valid" C++
    before ISO intervened, when we not only could, but did.

    --
    James Kanze (GABI Software) email:
    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
     
    James Kanze, Dec 16, 2007
    #7
  8. * James Kanze:
    > On Dec 16, 2:49 am, "Alf P. Steinbach" <> wrote:
    >> * James Kanze:
    >>>> [snip]

    >
    >>>>>> It does not happen when you return a reference from a function.

    >
    >>>>> Nor when you initialize a member. On the other hand, it applies
    >>>>> to global references just as much as to local ones.

    >
    >>>> That's true.

    >
    >>>>> [...]
    >>>>>> Consider

    >
    >>>>>> void increment( unsigned& x ) { ++x; }

    >
    >>>>>> int main() { int y = 0; increment( unsigned(y) ); }

    >
    >>>>>> The cast produces an rvalue. If this compiled it would presumably
    >>>>>> increment a temporary instead of y.

    >
    >>>>> Not "If this compiled", but "When it was legal C++ and
    >>>>> compiled".

    >
    >>>> Sorry, that's bull. It makes no sense to talk about "valid"
    >>>> (or "legal") C++ before standardization.

    >
    >>> You're either being intentionally obtuse, or just playing
    >>> stupid.

    >
    >> Are you really sure you want to go that road, James?

    >
    >> First posting a meaningless looks-like-a-clarification, then calling
    >> names when you're taken up on it?

    >
    > First, I don't think the clarification was meaningless, because
    > I've consistently encountered people who misunderstood the issue
    > when it was presented in that way. And second, the attack is
    > less ad hominim than a constatation concerning one particular
    > statement, or way of reasoning. You statement "It makes no
    > sense to talk about "valid" (or "legal") C++ before
    > standardization" is simply ridiculous, and I know you know
    > better. So I have to suppose that you're making it for some
    > sort of rhetorical reason: being intentionally obtuse, playing
    > stupid (since I know you're not), or trying to provoke some sort
    > of reaction I can't see.


    It really doesn't make sense. Different compilers implemented different
    languages. E.g., Borland's Turbo C++ implemented virtual calls from
    constructors as they work in Java today, and IIRC Microsoft's Visual C++
    (mid-90's) didn't have the exception classes specified by the draft.


    >>> So what was the language in which I wrote valid and
    >>> legal programs between 1991 (when I first started working
    >>> intensively in C++) and 1998 (when the standard was adopted).

    >
    >> Assuming you used more than one compiler or one compiler with
    >> more than one set of options, the languages you used were not
    >> standard C++, and they were not one language:

    >
    >> they were a number of slightly different languages, conforming in
    >> general to Bjarne Stroustup's "reference manual" for C++.

    >
    > I was there, and the ARM was taken very much as a "standard".
    > And with the exception of g++ (which really was a different
    > language at the time), conformance was generally better than
    > conformance to the ISO standard today. (Note that the chapters
    > in the ARM on templates and exceptions were considered more or
    > less experimental, and were not treated as part of the de facto
    > standard.)


    Well, there you have it: in order to come with anything resembling a
    common well-defined language you have to resort to a subjective view of
    which parts of the ARM -- or draft standard -- were significant.


    >> By (May) 1991 that reference manual had already made the
    >> change we're discussing here.

    >
    > Become a standard?


    Tell me, are you reading someone else's articles and answering mine?


    > Again, I was there, and there was no ISO
    > standard until 1998. And the text that would be the standard
    > didn't really stabilize until 1996-1997. Until well after the
    > 1998, most users considered the ARM as the reference, not the
    > ISO standard, simply because most compilers implemented
    > something much closer to the ARM than to the ISO standard.


    I think that was my point, earlier, but it doesn't hurt repeating. :)


    >> Programs using the earlier
    >> bind-temporary-to-reference-to-non-const could still compile
    >> and in that sense be valid (for a given compiler), for the
    >> intention was to "fade out" use of that feature.

    >
    > In 1991, yes. The rule was changed before the ARM, and by 1991,
    > the ARM was rapidly becoming the definition of what was legal
    > and valid C++. The rule wasn't present in earlier versions of
    > "The C++ Programming Language", however, which was the reference
    > before the ARM.
    >
    >> So your C++ programs written between 1991 and 1998 could get
    >> away with being valid for the compiler(s) used, but invalid
    >> wrt. the "reference manual", and neither valid nor invalid
    >> wrt. to any standard, not yet existing.

    >
    > A program which bound a temporary to a non-const reference
    > wasn't valid or legal in 1991.


    Again (but with suitable reinterpretation of "valid" or "legal" in the
    sense it seems you're using these words), I think that was *my* point,
    in response to your statement implying that you had bound temporaries to
    non-const references in programs you made between the years 1991 and
    1998, programs that by your definition of "legal" C++ were "legal". Hm.

    OK James, it doesn't matter much, this.

    I think you're writing late in the evening or something.


    [snip]
    >> So I think there were a number of factors influencing the decision.

    >
    > As I said, the reason you cited was the reason I'd always heard.
    > The example you gave is, in fact, the usual example I've seen.
    > I'm quite convinced that it is the explination of why the change
    > was made. My critical comment above is limited to your
    > statement that you couldn't talk about "legal" and "valid" C++
    > before ISO intervened, when we not only could, but did.


    Perhaps we're not really disagreeing about anything here except a bit of
    terminology.

    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Dec 16, 2007
    #8
  9. George2

    James Kanze Guest

    On Dec 16, 12:28 pm, "Alf P. Steinbach" <> wrote:
    > * James Kanze:


    [...]
    > >>>> Sorry, that's bull. It makes no sense to talk about "valid"
    > >>>> (or "legal") C++ before standardization.


    > >>> You're either being intentionally obtuse, or just playing
    > >>> stupid.


    > >> Are you really sure you want to go that road, James?


    > >> First posting a meaningless looks-like-a-clarification, then calling
    > >> names when you're taken up on it?


    > > First, I don't think the clarification was meaningless, because
    > > I've consistently encountered people who misunderstood the issue
    > > when it was presented in that way. And second, the attack is
    > > less ad hominim than a constatation concerning one particular
    > > statement, or way of reasoning. You statement "It makes no
    > > sense to talk about "valid" (or "legal") C++ before
    > > standardization" is simply ridiculous, and I know you know
    > > better. So I have to suppose that you're making it for some
    > > sort of rhetorical reason: being intentionally obtuse, playing
    > > stupid (since I know you're not), or trying to provoke some sort
    > > of reaction I can't see.


    > It really doesn't make sense. Different compilers implemented
    > different languages.


    No more so than today. You had a more or less formal
    specification (from AT&T, rather than from ISO), a number of
    implementations with more or less errors (rather more, back
    then, but I don't know of any compiler today without any errors
    either), and a few implementations which decided that they knew
    better, and intentionally implemented something different (but
    less than today---about the only compiler today which even tries
    to respect the standard is EDG).

    > E.g., Borland's Turbo C++ implemented virtual calls from
    > constructors as they work in Java today, and IIRC Microsoft's
    > Visual C++ (mid-90's) didn't have the exception classes
    > specified by the draft.


    In the mid-90's, no one (or almost no-one) had exceptions.

    As I said, templates and exceptions were more or less considered
    experimental extensions, weren't considered part of the
    "language", and weren't used if you were trying to be portable.

    Again, how does that differ from today? We have a specification
    for templates, but only EDG even tries to implement it.

    > >>> So what was the language in which I wrote valid and legal
    > >>> programs between 1991 (when I first started working
    > >>> intensively in C++) and 1998 (when the standard was
    > >>> adopted).


    > >> Assuming you used more than one compiler or one compiler
    > >> with more than one set of options, the languages you used
    > >> were not standard C++, and they were not one language:


    > >> they were a number of slightly different languages,
    > >> conforming in general to Bjarne Stroustup's "reference
    > >> manual" for C++.


    > > I was there, and the ARM was taken very much as a
    > > "standard". And with the exception of g++ (which really was
    > > a different language at the time), conformance was generally
    > > better than conformance to the ISO standard today. (Note
    > > that the chapters in the ARM on templates and exceptions
    > > were considered more or less experimental, and were not
    > > treated as part of the de facto standard.)


    > Well, there you have it: in order to come with anything
    > resembling a common well-defined language you have to resort
    > to a subjective view of which parts of the ARM -- or draft
    > standard -- were significant.


    Maybe those parts which the author said were significant, and
    not experimental? Or simply those parts which consensus had
    adopted.

    The fact remains that it was easier to write portable C++, which
    would be accepted by all compilers, in 1990, than it is today.

    [...]
    > > Again, I was there, and there was no ISO
    > > standard until 1998. And the text that would be the standard
    > > didn't really stabilize until 1996-1997. Until well after the
    > > 1998, most users considered the ARM as the reference, not the
    > > ISO standard, simply because most compilers implemented
    > > something much closer to the ARM than to the ISO standard.


    > I think that was my point, earlier, but it doesn't hurt
    > repeating. :)


    That may have been what you wanted to say, but it's not what you
    said. What you said was that there was no such thing as C++
    before the standard. That talking about "legal" and "valid" C++
    didn't make sense (although everyone using C++ back then did,
    and we knew what we were talking about).

    [...]
    > >> So your C++ programs written between 1991 and 1998 could get
    > >> away with being valid for the compiler(s) used, but invalid
    > >> wrt. the "reference manual", and neither valid nor invalid
    > >> wrt. to any standard, not yet existing.


    > > A program which bound a temporary to a non-const reference
    > > wasn't valid or legal in 1991.


    > Again (but with suitable reinterpretation of "valid" or
    > "legal" in the sense it seems you're using these words), I
    > think that was *my* point, in response to your statement
    > implying that you had bound temporaries to non-const
    > references in programs you made between the years 1991 and
    > 1998, programs that by your definition of "legal" C++ were
    > "legal". Hm.


    Woah. I didn't say that it was "valid" or "legal" in 1991. I
    said that there was a time in the past when it was valid and
    legal. That time is definitly before 1990: it was valid and
    legal when the first edition of "The C++ Programming Language"
    appeared, but the rule was changed sometime in the late 1980's.

    > [snip]
    > Perhaps we're not really disagreeing about anything here
    > except a bit of terminology.


    Isn't that usually the case with us:). (Except for iostream,
    of course.)

    --
    James Kanze (GABI Software) email:
    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
     
    James Kanze, Dec 17, 2007
    #9
  10. George2

    Rahul Guest

    On Dec 15, 9:50 am, George2 <> wrote:
    > Hello everyone,
    >
    > This is my understanding of non-const reference, const reference and
    > their relationships with lvalue/rvalue. Please help to review whether
    > it is correct and feel free to correct me. Thanks.
    >
    > 1. A const reference can be binded to a rvalue, for example, a
    > temporary object. And the "life" of the temporary object is guaranteed
    > to be extended and we can safely operate through the const-reference.
    >
    > 2. A non-const reference can not binded to a rvalue, I think the
    > reason is rvalue is not addressable? And we can not change the rvalue
    > through its reference? Are there any other reasons? I am not quite
    > sure whether my understanding is fully correct. Since there are some
    > non-modifiable lvalues (so we do not always need to modify values
    > through its reference). I am still studying what is the reason in
    > essence in compiler why a non-const reference can not be binded to a
    > rvalue.
    >
    > 3. Both const and non-const reference can be binded to a lvalue.
    >
    > thanks in advance,
    > George


    References are always const. There is no non-const reference... in
    fact reference is a kind of a const pointer which has to be
    initialized and once initialized can't be changed or modified...

    my compiler also gives me a warning for the following function,

    func(const int& const ref)
    {
    }

    indicating tht the second const isn't needed...
     
    Rahul, Dec 17, 2007
    #10
  11. George2

    Pete Becker Guest

    On 2007-12-17 05:20:20 -0500, Rahul <> said:

    >
    > References are always const. There is no non-const reference...


    That's literally true, but people sometimes use "const reference" to
    mean "reference to const object". It's imprecise, but usually not
    ambiguous or incorrect.

    --
    Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    Standard C++ Library Extensions: a Tutorial and Reference
    (www.petebecker.com/tr1book)
     
    Pete Becker, Dec 17, 2007
    #11
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dave

    Why const and non-const?

    Dave, Apr 21, 2004, in forum: C++
    Replies:
    1
    Views:
    305
    Cy Edmunds
    Apr 21, 2004
  2. Mark Stijnman
    Replies:
    2
    Views:
    504
    =?ISO-8859-15?Q?Juli=E1n?= Albo
    Apr 22, 2005
  3. Andrew Ward
    Replies:
    2
    Views:
    1,089
    Zorro
    Jul 19, 2005
  4. Javier
    Replies:
    2
    Views:
    607
    James Kanze
    Sep 4, 2007
  5. fungus
    Replies:
    13
    Views:
    930
    fungus
    Oct 31, 2008
Loading...

Share This Page