Re: How to detect const reference to temporary issues at compile or runtime?
On Dec 1, 2:18 am, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
On 11/30/2010 8:56 PM, Clinton Mead wrote:
I've found recently that most of the errors in my C++ programs are of
a form like the following example:
#include<iostream>
class Z
{
public:
Z(int n) : n(n) {}
int n;
};
class Y
{
public:
Y(const Z& z) : z(z) {}
const Z& z;
};
class X
{
public:
X(const Y& y) : y(y) {}
Y y;
};
class Big
{
public:
Big()
{
for (int i = 0; i< 1000; ++i) { a[i] = i + 1000; }
}
int a[1000];
};
X get_x() { return X(Y(Z(123))); }
int main()
{
X x = get_x();
Big b;
std::cout<< x.y.z.n<< std::endl;
}
OUTPUT: 1000
I would expect this program to output 123 (the value of x.y.z.n set in
get_x()) but the creation of "Big b" overwrites the temporary Z. As a
result, the reference to the temporary Z in the object Y is now
overwritten with Big b, and hence the output is not what I would
expect.
Simply put, your program has undefined behavior. You initialize the
data member of your 'Y' with a reference to a temporary. For a very
brief moment that reference is valid, then the temporary gets destroyed
and the reference becomes invalid. Any attempt to use it has undefined
behavior as the result.
I think he knows that. He's just wondering why compilers don't
warn in this simple case.
When I compiled this program with gcc 4.5 with the option "-Wall", it
gave no warning.
The compilers aren't *that* sophisticated. I don't know of any that
would exist that could determine the problem.
Using a reference parameter to initialize a reference member in
a constructor shouldn't be that hard to detect. The question is
whether it would result in too many false warnings: if your
"constract" says that the object passed in must live until the
end of the lifetime of the object being constructed, there's no
problem. Whether that's a frequent case or not in general,
I don't know. (It never occurs in my own code, because my
personal coding guidelines insist on using a pointer when an
argument must live beyond the end of the function: a pointer
means you need an lvalue, so trying to pass a temporary causes
a compiler error.)
--
James Kanze