I've noticed a slight discrepency in how MSVC and g++ handle creation of the temporary exception object when the thrown type is movable. Hunting these down raised additional questions. 

Before going any further, here is the core of my question: in the absense of copy/move elision, who well does the standard say how the temporary exception object should be created? At the moment, the best I've been able to do is the following quote, from 15.1/3:

> 
> A throw-expression initializes a temporary object, called the exception object, the type of which is determined by removing any top-level cv-qualifiers from the static type of the operand of throw and adjusting the type from “array of T” or “function returning T” to “pointer to T” or “pointer to function returning T”, respectively.
> 
> 
> 

I'm guessing the answer is buried somewhere in language elsewhere that defines the type of an expression and how objects are initialized, but I'm having no luck piecing it all together. When an object is thrown, does the exception object get (a) copy constructed, (b) move constructed if appropriate, and copy constructed otherwise, or (c) initialized in an implementation defined manner?

Consider the following code:

```
#include <iostream>
using std::cout;
using std::cin;
using std::endl;

struct Blob {
  Blob() { cout << "C" << endl; }
  Blob(const Blob&) { cout << "c" << endl; }
  Blob(Blob&&) { cout << "m" << endl; }
  Blob& operator =(const Blob&) { cout << "=" << endl; return *this; }
  Blob& operator =(Blob&&) { cout << "=m" << endl; return *this; }
  ~Blob() { cout << "~" << endl; }

  int i;
};

int main() {
  try {
     cout << "Throw directly: " << endl;
     throw Blob();
  } catch(const Blob& e) { cout << "caught: " << &e << endl; }
  try {
     cout << "Throw with object about to die anyhow" << endl;
     Blob b;
     throw b;
  } catch(const Blob& e) { cout << "caught: " << &e << endl;  }
  {
    cout << "Throw with object not about to die anyhow (enter non-zero integer)" << endl;
    Blob b;
    int tmp;
    cin >> tmp; //Just trying to keep optimizers from removing dead code
    try {
      if(tmp) throw b;
      cout << "Test is worthless if you enter '0' silly" << endl;
    } catch(const Blob& e) { cout << "caught: " << &e << endl;  }
    b.i = tmp;
    cout << b.i << endl;
  }
}

```

This is all recreated on [ideone](http://ideone.com/bA4iO). As you can [hopefully] see, gcc via ideone creates the `Blob` object in place in the first case, and moves in the second two. The results are summarized below, with the pointer values replaced with identifiers. 

```
Throw directly: 
C {A}
caught: {A}
~ {A}
Throw with object about to die anyhow
C {A}
m {B} <- {A}
~ {A}
caught: {B}
~ {B}
Throw with object not about to die anyhow (enter non-zero integer)
C {A}
m {B} <- {A}
caught: {B}
~ {B}
2
~ {A}

```

The same code in MSVC2010, regardless of optimization settings, the results are the same except the two moves are copies. This is the difference that initially caught my eye.

The first test I assume is fine; its classic copy elision.

In the second test, gcc behaves the way I would have expected. The temporary `Blob` is treated as an xvalue, and the exception object is move constructed from it. But I'm not sure if the compiler is required to recognize that the original `Blob` is expiring; if it isn't it, then MSVC is acting correctly when it copies. Thus my original question: does the standard mandate what happens here, or is it just part of the implementation defined behavior inherant to exception handling? 

The third test is exactly the opposite: MSVC behaves the way my intuition demands. gcc choses to move from `b`, but `b` is still live, as evidenced by the fact that I continue to work with it after handling the thrown exception. Obviously, in this trivial example, moving or copying makes no difference to `b` itself, but surely the compiler isn't allowed to look at that when considering overload resolution.

Obviously, the presence of copy/move elision makes this simple test hard to generalize from, but the bigger issue is that either compiler might not be complient just yet [particularly in gcc's case with the third test, and MSVC in general]. 

Note this is entirely for academic purposes; I almost never throw anything except a temporary, which both compilers construct in place anyhow, and I'm quite certain that behavior is allowed.