问题
Short question, is the following ok:
struct X
{
A& x;
A y;
X() : x(y) {}
};
Reversing the order of the two members in the struct is definitely ok, since it guarantees y is initialized first, but does this work or invoke UB?
Moreso, would the following be ok:
struct X
{
X& x;
X() : x(*this) {}
};
?
回答1:
I don't think that would invoke undefined behavior.
I don't see that case is any different from this:
int *p = new int;
The expression new int is a pointer to an uninitialized int. Here we are initializing the pointer p with new int. The content is not read.
Similarly,
int & r = *p; //or *new int
Here we are initializing the reference r with *p. The content is not read
In both cases, the content is not read. Reading an uninitialized variable invokes undefined behavior. In both cases, it is the content which is uninitialized, not the address, and we are not reading the content.
回答2:
The reference and the variable are distinct things each has its own "initialization".
The purpose of a reference is to refer to something. The only prerequisite is that something physically exist. Whatever its state is well defined or not is all another story.
The initialization of the reference is not UB. It can be UB its use, before what it refer had been given a value, but this is no more no less what you get when using an initialized variable.
Different thing is X() :x(*this) {}
Here you are giving to a function (the x constructor) a pointer to something that is not yet been fully constructed. This is "dangerous" since -in general- you don't know what that function will do with that pointer and if it expects or not it to be somehow "flawled". May be it just "store it for later use" (hence no problem) may be it deference it to access ... unreconstructed members! It is something a compiler should at least warn about.
Of course, in this particular case (you are just initializing a reference) it will not be a problem since a "reference contructor" don't access the referred object. But in general is not a good idea.
回答3:
I think that it would make sense to split this issue into several other points:
- Is this syntactically correct and does this allow only one implementation?
- Can this code lead to crashes and high level issues?
- Should the compiler take care of the second?
I would answer: Y, Y, Y/N.
I do not see ambiguity in the samples of the code above. There are millions of ways how syntactically correct code would corrupt memory, crash, etc. This is yet another example.
Compiler may issue a warning, because the examples above are obvious. In a real scenario with a lot of indirections, redefinitions, etc, compiler may get confused. I would not blame it too hard. Algorithmic analysis is a job of another tool, not the compiler.
For example the code below is perfectly fine:
int *p = NULL;
int &r = *p;
This is NULL reference. Nothing special.
These are my 2 cents.
来源:https://stackoverflow.com/questions/11338601/can-you-bind-a-reference-to-an-uninitialized-member