why should throwing an exception by reference work

P

puzzlecracker

puzzlecracker said:
It shouldnt, since reference object is destroyed in the stack frame.
in this example

void bar(){
MyExcepton ex(); //MyException inherits from Excetpion
Exception &exRef=ex;
throw exRef;

}

void foo(){

try{

bar();
}catch( Exception &ex){

}catch(...){}
 
A

Andre Kostur

in this example

void bar(){
MyExcepton ex(); //MyException inherits from Excetpion
Exception &exRef=ex;
throw exRef;

}

void foo(){

try{

bar();
}catch( Exception &ex){

}catch(...){}


Ah... but when the exception is thrown... a copy is taken and put
/somewhere/ (implementation-defined, I believe). So when you catch,
you're getting a reference to that copied object.
 
A

Andre Kostur

BTW, doesn't this declare a function named "ex", taking no parameters, and
returning and object of type MyException, by value?
 
T

Tomás

void bar(){
MyExcepton ex(); //MyException inherits from Excetpion

That's a very pretty function declaration you have there. It's exactly the
same as writing:

MyException ex(void);

ReturnType FunctionName(ParameterList);

What you want is:

My Exception ex;
Exception &exRef=ex;
throw exRef;

}

void foo(){

try{

bar();
}catch( Exception &ex){


You have an invalid reference here, because the object to which it refers
has gone out of scope (i.e. has been destroyed).

You could throw a reference if it's valid. For example:

int global_var = 2;

int main()
{
try
{

throw global_var;
}
catch (int &i)
{
i = 7;
}
}


-Tomás
 
J

John Carson

Tomás said:
That's a very pretty function declaration you have there. It's
exactly the same as writing:

MyException ex(void);

ReturnType FunctionName(ParameterList);

What you want is:

My Exception ex;



You have an invalid reference here, because the object to which it
refers has gone out of scope (i.e. has been destroyed).

I don't believe that is correct. Consider:

#include <iostream>
using namespace std;

struct MyException
{
int a;
};

void bar()
{
MyException me = {4};
MyException &meRef = me;
throw meRef;
}

int main()
{
try
{
bar();
}
catch( MyException &me)
{
cout << "integer is " << me.a << '\n';
}
return 0;
}

This works as it should on VC++ 8 and compiles without warnings on both VC++
8 and Comeau online.

I believe the relevant section of the standard is 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. [Note: the temporary object
created for a throw-expression that is a string literal is never of type
char* or wchar_t*; that is, the special conversions for string literals from
the types "array of const char" and "array of const wchar_t" to the types
"pointer to char" and "pointer to wchar_t", respectively (4.2), are never
applied to a throw-expression. ] The temporary is used to initialize the
variable named in the matching handler (15.3)."

On my reading, this means that the throw expression creates its own
temporary, so it is not dependent on the one declared inside bar() in the
code above (15.1/5 says that the creation of the temporary may be eliminated
if it doesn't change the meaning of the program).

It is of some interest to note that it apparently not necessary to make the
argument to catch() const in spite of the fact that it is being initialized
by a temporary.
 
P

puzzlecracker

John said:
Tomás said:
That's a very pretty function declaration you have there. It's
exactly the same as writing:

MyException ex(void);

ReturnType FunctionName(ParameterList);

What you want is:

My Exception ex;



You have an invalid reference here, because the object to which it
refers has gone out of scope (i.e. has been destroyed).

I don't believe that is correct. Consider:

#include <iostream>
using namespace std;

struct MyException
{
int a;
};

void bar()
{
MyException me = {4};
MyException &meRef = me;
throw meRef;
}

int main()
{
try
{
bar();
}
catch( MyException &me)
{
cout << "integer is " << me.a << '\n';
}
return 0;
}

This works as it should on VC++ 8 and compiles without warnings on both VC++
8 and Comeau online.

I believe the relevant section of the standard is 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. [Note: the temporary object
created for a throw-expression that is a string literal is never of type
char* or wchar_t*; that is, the special conversions for string literals from
the types "array of const char" and "array of const wchar_t" to the types
"pointer to char" and "pointer to wchar_t", respectively (4.2), are never
applied to a throw-expression. ] The temporary is used to initialize the
variable named in the matching handler (15.3)."

On my reading, this means that the throw expression creates its own
temporary, so it is not dependent on the one declared inside bar() in the
code above (15.1/5 says that the creation of the temporary may be eliminated
if it doesn't change the meaning of the program).

It is of some interest to note that it apparently not necessary to make the
argument to catch() const in spite of the fact that it is being initialized
by a temporary.

John - that does it, i guess.

Reading Java Language specification
(http://java.sun.com/docs/books/jls/third_edition/html/j3TOC.html) is
much easier than c++ standard.... is that why c++ is dying?:)
 
E

Earl Purple

John said:
It is of some interest to note that it apparently not necessary to make the
argument to catch() const in spite of the fact that it is being initialized
by a temporary.

probably because there is no chance of an implicit conversion in a
catch. It simply won' catch.

void foo()
{
throw ("text");
}

void bar()
{
try
{
foo();
}
catch ( std::string & s ) // won't catch the exception
{
s.push_back( 'X' );
}
}

And if you put const std::string & instead it still won't catch it.
 
P

puzzlecracker

Earl said:
probably because there is no chance of an implicit conversion in a
catch. It simply won' catch.

void foo()
{
throw ("text");
}

void bar()
{
try
{
foo();
}
catch ( std::string & s ) // won't catch the exception
{
s.push_back( 'X' );
}
}

And if you put const std::string & instead it still won't catch it.

why not?

is it because, you're throwing char *???
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top