Qt-interest Archive, August 2007
error: initial value of reference to non-const must be an lvalue?
Message 1 in thread
Hi QtXml developers,
I have a recursive funtion:
void ...::updateHref(QDomElement &e)
{
....
updateHref(e.nextSiblingElement());
}
Windows compiler says ok, but Linux compiler says error:
"error: initial value of reference to non-const must be an lvalue"
Then, I have to split the one line of code into two lines
QDomElement sibling = e.nextSiblingElement();
updateHref(sibling);
Why's that?
Thanks,
Lingfa
--
[ signature omitted ]
Message 2 in thread
On 07.08.07 16:26:05, Lingfa Yang wrote:
> Hi QtXml developers,
>
> I have a recursive funtion:
> void ...::updateHref(QDomElement &e)
> {
> ....
> updateHref(e.nextSiblingElement()); }
>
> Windows compiler says ok, but Linux compiler says error:
>
> "error: initial value of reference to non-const must be an lvalue"
>
> Then, I have to split the one line of code into two lines
> QDomElement sibling = e.nextSiblingElement();
> updateHref(sibling);
>
> Why's that?
Because your windows compiler is broken (or automatically removes the
const). nextSiblingElement doesn't return a reference, but a copy of the
element and its const. So you're code is not doing what you expect it to
do anyway (i.e. it doesn't change the element you give to updateHref).
Andreas
--
[ signature omitted ]
Message 3 in thread
>element and its const. So you're code is not doing what you expect it to
>do anyway (i.e. it doesn't change the element you give to updateHref).
>
>
>
I just made a test both cases work fine on Windows. I mean it does
change the element as I expecte.
--
[ signature omitted ]
Message 4 in thread
On 07.08.07 17:56:37, Lingfa Yang wrote:
>
> >element and its const. So you're code is not doing what you expect it to
> >do anyway (i.e. it doesn't change the element you give to updateHref).
> >
> >
> I just made a test both cases work fine on Windows. I mean it does change the
> element as I expecte.
Indeed, but this is only because QDomNode shares its data explicitly.
You should add a note about that to your function. If you use objects
that don't share their data like QDomNode then you'd see the same result
before and after executing your function.
As for why gcc wants you to create an object: Because else you might use
a reference that "points" to nothing, because the object returned from
the function call is temporary and goes out of scope as soon as the
statement finishes. So as the compiler can't easily know (read in little
time) what you do with that reference it forbids to use a temporary to
pass it as reference around.
You could do something like
class MyBrokenClass
{
QDomElement& m_myBreakingReference;
}
void MyBrokenClass::doSomething(QDomElement& e)
{
m_myBreakingReference = e;
}
void MyBrokenClass::doSomethingElse( QDomNode n )
{
doSomething(n.nextSiblingElement());
m_myBreakingReference->setTagName("foo");
}
This would break on the last line because the object that
m_myBreakingReference references doesn't exist anymore at that point.
You'd get a crash if the compiler wouldn't prevent you from using the
function call directly.
The same crash will happen when you fix that above code with your
solution and then access m_myBreakingReference outside of
"doSomethingElse".
Oh, and btw, due to the explicit-sharing-natuer of QDomNode and
subclasses you don't need that reference in your function anyway. Even
if you hand over a copy you alter the same underlying data, so just
remove the & there (or replace with const foo& to save some memory)
Andreas
--
[ signature omitted ]
Message 5 in thread
The gcc compiler is correct. You are allowed to pass a temporary
variable (e.nextSiblingElement() in this case) by const reference, but
you may not pass a non-const reference to a temporary as a function
argument. Your work around is the correct way to do this.
See the temporaries section on this page for another explanation:
http://web.mit.edu/merolish/ticpp/Chapter08.html
Paul.
Lingfa Yang wrote:
> Hi QtXml developers,
>
> I have a recursive funtion:
> void ...::updateHref(QDomElement &e)
> {
> ....
> updateHref(e.nextSiblingElement()); }
>
> Windows compiler says ok, but Linux compiler says error:
>
> "error: initial value of reference to non-const must be an lvalue"
>
> Then, I have to split the one line of code into two lines
> QDomElement sibling = e.nextSiblingElement();
> updateHref(sibling);
>
> Why's that?
>
> Thanks,
> Lingfa
>
>
> --
> To unsubscribe - send a mail to qt-interest-request@xxxxxxxxxxxxx with
> "unsubscribe" in the subject or the body.
> List archive and information: http://lists.trolltech.com/qt-interest/
>
--
[ signature omitted ]
Message 6 in thread
On 07.08.07 16:45:25, Paul Koshevoy wrote:
> The gcc compiler is correct. You are allowed to pass a temporary variable
> (e.nextSiblingElement() in this case) by const reference, but you may not pass
> a non-const reference to a temporary as a function argument. Your work around
> is the correct way to do this.
Well not quite, as that is still a temporary variable and if he stores a
reference to that variable and tries to access it after that temporary
variable has been destroyed (i.e. after the function updateHref exited)
he'll get a crash or strange behaviour still. And such bugs are quite
hard to find.
Andreas
--
[ signature omitted ]
Message 7 in thread
Andreas Pakulat wrote:
> On 07.08.07 16:45:25, Paul Koshevoy wrote:
>> The gcc compiler is correct. You are allowed to pass a temporary variable
>> (e.nextSiblingElement() in this case) by const reference, but you may not pass
>> a non-const reference to a temporary as a function argument. Your work around
>> is the correct way to do this.
>
> Well not quite, as that is still a temporary variable and if he stores a
> reference to that variable and tries to access it after that temporary
> variable has been destroyed (i.e. after the function updateHref exited)
> he'll get a crash or strange behaviour still. And such bugs are quite
> hard to find.
Never the less, the compiler must allow passing a temporary by const reference
-- it's perfectly legal within the language. Whether you choose to hold on to
that temporary or not is not compiler an issue. Passing a non-const reference to
a temporary is not legal.
http://web.mit.edu/merolish/ticpp/Chapter08.html
Paul.
--
[ signature omitted ]
Message 8 in thread
On 07.08.07 20:07:51, Paul Koshevoy wrote:
>
>
> Andreas Pakulat wrote:
> > On 07.08.07 16:45:25, Paul Koshevoy wrote:
> >> The gcc compiler is correct. You are allowed to pass a temporary variable
> >> (e.nextSiblingElement() in this case) by const reference, but you may not pass
> >> a non-const reference to a temporary as a function argument. Your work around
> >> is the correct way to do this.
> >
> > Well not quite, as that is still a temporary variable and if he stores a
> > reference to that variable and tries to access it after that temporary
> > variable has been destroyed (i.e. after the function updateHref exited)
> > he'll get a crash or strange behaviour still. And such bugs are quite
> > hard to find.
>
> Never the less, the compiler must allow passing a temporary by const reference
> -- it's perfectly legal within the language. Whether you choose to hold on to
> that temporary or not is not compiler an issue. Passing a non-const reference to
> a temporary is not legal.
Well, actually its still a temporary, just that its life-duration is
extended to the current scope. I think this is just something that the
compiler doesn't check in this case because it would take considerable
amount to check wether a given object thats passed as non-const
reference was created inside a function. (I might be completely wrong
there, don't know that much about current compilers internals)
Andreas
--
[ signature omitted ]