5

I wrote the following code to test this:

struct X
{
   char* x;
   X()
   {
      x = new char('a');
   }
   ~X()
   {
      *x = 'b';
      delete x;
   }
};

void foo(const X& x)
{
}
void goo(X& x)
{
}

int main()
{
   foo(X());
   goo(X());
}

The destructors for the temporaries are called after both functions exit, but I thought you can only bind a temporary to a const reference. Why does goo work then?

Is it UB and MSVS is wrong, or is it ok?

AMCoder
  • 773
  • 1
  • 6
  • 15
  • "Is it UB and MSVS is wrong" - if it's UB MSVS *cannot* be wrong by definition, because UB manifestations include "everything working as expected" (for every value of "as expected"). – Matteo Italia May 16 '12 at 08:57
  • This is a dupe to another question. And yes, MSVC is being naughty here, check ideone: http://ideone.com/zykx9. – Pubby May 16 '12 at 08:58
  • 1
    possible duplicate of [How come a non-const reference cannot bind to a temporary object?](http://stackoverflow.com/questions/1565600/how-come-a-non-const-reference-cannot-bind-to-a-temporary-object) – iammilind May 16 '12 at 08:58
  • 1
    If you set the warning level to 4, then you should get a warning like this. " nonstandard extension used : 'argument' : conversion from 'X' to 'X &' " – Jagannath May 16 '12 at 09:28
  • 1
    If you set "disable language extensions" to Yes, you get error in MSVC2010. Configuration Properties -> C/C++ ->"Language->Disable language extensions" = Yes. – Jagannath May 16 '12 at 10:16

2 Answers2

3

It's illegal. A conforming implementation diagnoses it (i.e. it must at least warn), but MSVC++ allows it as an extension.

Or a bug if you're unkind, but IIRC the reason they still allow it is for long-lived legacy reasons: nominally to support code written for MSVC++ before C++ was standardized, but of course once you allow people to write this, they write it accidentally in new code too, so the legacy lives on. If it's deliberate then it's a (mis-)feature, not a bug, right? Anyway, a conforming implementation is required to diagnose ill-formed programs, so if you don't get a warning then the compiler isn't conforming.

Steve Jessop
  • 273,490
  • 39
  • 460
  • 699
  • I don't like the word "bug"; error is a much more accurate word. And if it's deliberate, then it's not an error, at least not a programming error. (The decision to support it _is_ an error, since the rule forbidding binding to a non-const reference predates the first MS C++ compiler by at least 5 years. When MS introduced their first C++ compiler, CFront already warned about using a deprecated feature in this case.) – James Kanze May 16 '12 at 09:03
  • @James: given MS's "embrace and extend" approach to standards, I can just imagine how much weight they gave to a "rule" pre-standards. After all, who does Bjarne think he is, the inventor of the language or something? ;-) – Steve Jessop May 16 '12 at 09:06
  • 1
    Note that, at least for VS2008, VS will emit a *warning* for using any compiler extensions, including this one. There is even a compiler switch to shut them off. Just like for GCC. So if you're going to accuse MS of "embrace and extend" with this, should we not include the innumerable GCC extensions that some projects won't compile without? – Nicol Bolas May 16 '12 at 09:28
  • @Nicol: I don't accuse MS of anything *with this*, I said *if* it doesn't warn then it doesn't conform. If it warns, that's great, although I suspect the OP didn't see the warning for some reason or other. The DoJ accused MS of "embrace and extend" on the basis of the testimony before it regarding the words and actions of MS executives. But I was only semi-serious: my point was just that James calls this a rule of C++, which it is, but realistically MS was going to do whatever it wanted with its own C++ implementation, *especially* pre-standard. – Steve Jessop May 16 '12 at 09:40
  • And btw I would (and do) accuse most compilers of being non-conforming with their default options. Without at least `--warn-pedantic` GCC doesn't conform either in respect of diagnosing ill-formed programs, although I don't think it has this particular extension with any options. Whether that can be related to a broader "embrace and extend" strategy on the part of GNU is pure insinuation ;-) – Steve Jessop May 16 '12 at 09:47
1

This is apparently a MS extension. In GCC 4.3.4, for instance, it fails to compile, with the following message:

prog.cpp: In function ‘int main()’:
prog.cpp:25: error: invalid initialization of non-const reference of type ‘X&’ from a temporary of type ‘X’
prog.cpp:18: error: in passing argument 1 of ‘void goo(X&)’
Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680