关于错误的构造函数

关于异常的构造函数
程序如下:
#include <iostream>
#include <string>
using   namespace   std;
class   A
{
public:
        char   str[100];
A(char   *a= "a ")
{
cout < < "Hello: " < <a < <endl;
        strcpy(str,a);
}
void   print(){cout < < "print: " < <str < <endl;}
~A()
{
cout < < "goodbye: " < <str < <endl;
}
};
void   test()  
{
A   a( "test ");
throw   a;
}
int   main()
{
try{
test();
}
catch(A   a)
{
a.print();
}
}

为什么程序有下面的输出
Hello:test
goodbye:test
print:test
goodbye:test
goodbye:test
请按任意键继续.   .   .
问题1:好像多构造成了一个对象啊,它是在哪构造的呢,有什么用处?,我加上复制构造函数后就正常了,

问题2:另外,catch(A   a)为什么不能换成catch(A   a( "?? "))
第一次学习异常,有些不大明白

------解决方案--------------------
A a( "test ");
throw a;
catch(A a)
这三行 分别建立了三个对象,所以调用了1次构造函数 2次复制构造函数和3次析构函数,
catch是捕捉异常,不是建立对象 一般的用法应该是catch(A &a) 这样就少建立一个对象了
------解决方案--------------------
1.第一对Hello和goodbye是由你void test( )中定义的a打出的,因为你抛出一场会导致栈回滚,该自动变量会被析构。throw a会调用一个拷贝构造函数生成一个专门的异常对象,然后该异常对象被传递给catch的形参,再次调用拷贝构造函数生成第二个对象,故在程序结束时会有两个析构函数调用。
2.catch中的是形参列表,就理解成和函数形参差不多吧,函数形参中也没有那种表示方法吧。
------解决方案--------------------
catch( A a ){...}构造了一个对象作为参数传入,然后将此参数拷贝一份,即调用默认的拷贝构造函数。
------解决方案--------------------
C++社群中有条经验就是“尽量按引用捕获异常”。