今天在github看到有人抛出如下异常:throw std::exception("Invalid input."); 即抛出了一个匿名对象。
就比较了一下c++标准和各平台的实现:https://blog.csdn.net/a3192048/article/details/81329976
顺便也整理下c++的匿名对象。
- C++中的匿名对象是
pure RValue
, 因而不能作为引用传进去。 - 匿名对象只存在于构造该对象的那行代码,离开构造匿名对象的哪行代码后立即调用析构函数。
例1:
#include <iostream>
using namespace std;
class Test
{
int n;
public:
Test(int s) { n = s; }
~Test() {
cout << "Destructor" << endl;
}
int ret() { return n; }
};
int main()
{
cout << Test(666).ret() << endl; // 匿名对象只存在于该行代码,离开这行代码后立即调用析构函数。
cout << "test" << endl;
return 0;
}
输出:
例2:匿名对象的生命周期
#include <iostream>
#include <string>
using namespace std;
class Teacher
{
string name;
string course;
public:
Teacher() {
cout << "Default constructor " << endl;
}
Teacher(const char* n, const char*c) :name(n), course(c) {
cout << "constructor " << course << "'s teacher is " << name << endl;
}
Teacher(const Teacher& t) :name(t.name), course(t.course) {
cout << "Copy Constructor " << course << "'s teacher is " << name << endl;
}
~Teacher() {
cout << "Destructor " << course << "'s teacher is " << name << endl;
}
Teacher& operator=(const Teacher& p)
{
cout << "Assign" << endl;
return *this;
}
};
int main()
{
Teacher *t5 = new Teacher; // 或Teacher *t5 = new Teacher(); new没有产生匿名对象,可参考:https://blog.csdn.net/a3192048/article/details/80213288
cout << "=======0" << endl;
Teacher *t0 = new Teacher("Mr Hu", "Python");
cout << "=======1" << endl;
Teacher t1("Mr Zhao", "C++");
cout << "=======2" << endl;
Teacher t2 = t1;//初始化
cout << "=======3" << endl;
/* 这行代码的运行结果有点“出人意料”,从思维逻辑上说,当匿名对象创建了后,是应该调用自定义拷贝构造函数,或者是默认拷贝构造函数来完成复制过程的,但事实上系统并没有这么做,因为匿名对象使用过后在整个程序中就失去了作用,对于这种情况c++会把代码看成是:
Teacher t3("Ms Wang", "Matlab");
省略了创建匿名对象这一过程,所以说不会调用拷贝构造函数。 */
Teacher t3 = Teacher("Ms Wang", "Matlab");//用临时对象来初始化一个新对象,编译器一般会优化成直接用创建临时对象的参数来创建新对象。
cout << "=======4" << endl;
t2 = t3;//不会调用构造函数,因为没有创建新对象,赋值
cout << "=======5" << endl;
t2 = Teacher("Ms Li", "Consult");//赋值,临时对象会立即释放
cout << "=======6" << endl;
delete(t5);
delete(t0);
return 0;
}
输出:
例3:
#include <iostream>
using namespace std;
class exception
{
public:
exception()
{
cout << "Default Constructor" << endl;
}
exception(const exception& obj)
{
cout << "Copy Constructor" << endl;
}
~exception()
{
cout << "Destructor" << endl;
}
};
/* 注:exception前加::是为了调用全局的exception类,即自定义的exception,而不是库中的! */
int main()
{
/* 在执行此代码时,利用默认构造函数生成了一个匿名对象;执行完此行代码,
因为外部没有接此匿名对象的变量,此匿名又被析构了 */
::exception(); // 如改为 ::exception; 则编译不会报错,不会调用构造,析构函数。
/* 在执行此代码时,利用默认构造函数生成了一个匿名对象;然后将此匿名变成了a这个实例对象,此匿名对象没有被析构。 */
::exception a = ::exception(); // 改为 ::exception a = ::exception; 则编译报错!
cout << "===========" << endl;
return 0;
}
输出: