C++的匿名对象

今天在github看到有人抛出如下异常:throw std::exception("Invalid input."); 即抛出了一个匿名对象。

就比较了一下c++标准和各平台的实现:https://blog.csdn.net/a3192048/article/details/81329976

顺便也整理下c++的匿名对象。

  1. C++中的匿名对象是pure RValue, 因而不能作为引用传进去。
  2. 匿名对象只存在于构造该对象的那行代码,离开构造匿名对象的哪行代码后立即调用析构函数。

例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;
}

输出:

posted @ 2018-08-01 21:35  Adano1  阅读(406)  评论(0编辑  收藏  举报