Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 6042683
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 23, 20262026-05-23T06:49:03+00:00 2026-05-23T06:49:03+00:00

I’ve noticed a slight discrepency in how MSVC and g++ handle creation of the

  • 0

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. 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.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-23T06:49:03+00:00Added an answer on May 23, 2026 at 6:49 am

    The move behavior is conforming for case 2, but not case 3. See 12.8 [class.copy]/p31:

    When certain criteria are met, an
    implementation is allowed to omit the
    copy/move construction of a class
    object, even if the copy/move
    constructor and/or destructor for the
    object have side effects. …

    …

    • in a throw-expression, when the operand is the name of a non-volatile
      automatic object (other than a
      function or catch-clause parameter)
      whose scope does not extend beyond the
      end of the innermost enclosing
      try-block (if there is one), the
      copy/move operation from the operand
      to the exception object (15.1) can be
      omitted by constructing the automatic
      object directly into the exception
      object

    The above doesn’t define when an object can be implicitly moved. But it does define when copy/move elision is legal. To get when implicit move is legal you have to go down to paragraph 32 in the same section:

    32 When the criteria for elision of a
    copy operation are met or would be met
    save for the fact that the source
    object is a function parameter, and
    the object to be copied is designated
    by an lvalue, overload resolution …

    This paragraph explains that when copy/move elision is legal, then overload resolution happens with two passes:

    1. First pretend the lvalue is an rvalue in deciding what constructor is going to be called or elided.

    2. If 1) fails, then repeat overload resolution with the argument as an lvalue.

    This has the effect of producing a hierarchy of move semantics from best to worst:

    1. If you can elide construction, do so.
    2. Else if you can move the object out, do so.
    3. Else if you can copy the object out, do so.
    4. Else emit a diagnostic.

    Note that these are essentially the same rules for the ordinary return of local stack objects.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

link Im having trouble converting the html entites into html characters, (&# 8217;) i
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this
I'm trying to convert HTML to plain text. I get many &\#8217; &\#8220; etc.
i got an object with contents of html markup in it, for example: string
I am using Paperclip to handle profile photo uploads in my app. They upload
Let's say I'm outputting a post title and in our database, it's Hello Y&#8217;all
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I have a .ini file as follows: [playlist] numberofentries=2 File1=http://87.230.82.17:80 Title1=(#1 - 365/1400) Example
I am trying to understand how to use SyndicationItem to display feed which is
That's pretty much it. I'm using Nokogiri to scrape a web page what has

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.