C++使用引用计数的例子:表达式求值

             在引用计数中,每一个对象负责维护对象所有引用的计数值。当一个新的引用指向对象时,引用计数器就递增,当去掉一个引用时,引用计数就递减。当引用计数到零时,该对象就将释放占有的资源。这种计数应用十分广泛,比如java和C#等支持垃圾回收机制的语言编译器实现,COM组件的维护(com组件将维护一个称作是引用计数的数值。当客户从组件取得一个接口时,此引用计数值将增1。当客户使用完某个接口后,组件的引用计数值将减1.当引用计数值为0时,组件即可将自己从内存中删除),操作系统资源的管理等。

            C++语言不支持垃圾回收机制,但是可以通过使用引用计数来模拟垃圾回收机制,也可以通过应用计数来管理“大数据类”(拷贝负值构造出新对象,代价较大),这样可以提高性能。实际上,引用计数并不总是性能获益者,引用计数、执行速度和资源约束是一种相互关系,这个需要程序员综合评估。

            本文下面给出的代码是《C++沉思录》中的一个典型例子,个人觉得对于理解引用计数十分典型,虽然可能用引用计数显得不是特别必要,毕竟对象复制构造拷贝代价不是特别大,除非“表达式特别复杂”。其中,为了测试引用计数的析构函数是否在引用计数为0时释放,在DEBUG版本下面会显示析构情况。

#ifndef __EXPR__H__
#define __EXPR__H__

#include <iostream>
#include <string>

namespace smy
{
class Expr
{	
	// 内部类
	class Expr_node
	{
		friend std::ostream& operator<<(std::ostream&, const Expr&);
		friend std::ostream& operator<<(std::ostream& o, const Expr::Expr_node& e);
		friend class Expr;

		int use;
	protected:
		Expr_node() 
			: use(1) {}
		virtual void print(std::ostream&) const = 0;
		virtual int eval() const = 0;
		virtual ~Expr_node()
		{ 
#ifdef _DEBUG
			std::cout << "Expr_node::~Expr_node()" << std::endl; 
#endif
		}
	};
	// 整数
	class Int_node
		: public Expr_node
	{
		friend class Expr;

		int n;
	protected:
		Int_node(int k)
			: n(k) {}
		void print(std::ostream& o) const { o << n; }
		int eval() const { return n; }
		~Int_node() 
		{
#ifdef _DEBUG
			std::cout << "Int_node::~Int_node() " << *this << std::endl;
#endif
		}
	};
	// 单目运算符
	class Unary_node
		: public Expr_node
	{
		friend class Expr;

		std::string op;
		Expr_node* opnd;
	protected:
		Unary_node(const std::string& a, Expr_node* b)
			: op(a), opnd(b) { opnd->use++; }
		void print(std::ostream& o) const { o << "(" << op << *opnd << ")"; }
		int eval() const 
		{
			if (op == "-")
				return -opnd->eval();
			throw "error, bad op!";
		}
		~Unary_node() 
		{ 
#ifdef _DEBUG
			std::cout << "Unary_node::~Unary_node() " << *this << std::endl;
#endif
			if (--opnd->use == 0)
				delete opnd;
		}
	};
	// 双目运算符
	class Binary_node
		: public Expr_node
	{
		friend class Expr;

		std::string op;
		Expr_node* left;
		Expr_node* right;
	protected:
		Binary_node(const std::string& a, Expr_node* b, Expr_node* c)
			: op(a), left(b), right(c) { b->use++; c->use++; }
		void print(std::ostream& o) const { o << "(" << *left << op << *right << ")"; }
		int eval() const
		{
			int op1 = left->eval();
			int op2 = right->eval();
			if (op == "-")
				return op1 - op2;
			else if (op == "+")
				return op1 + op2;
			else if (op == "*")
				return op1 * op2;
			else if (op == "/")
			{
				if (op2 == 0)
					throw "error, bad /0!";
				return op1 / op2;
			}
			else if (op == "%")
			{
				if (op2 == 0)
					throw "error, bad %0!";
				return op1 % op2;
			}
			else
				throw "error, bad op!";
		}
		~Binary_node()
		{
#ifdef _DEBUG
			std::cout << "Binary_node::~Binary_node() " << *this << std::endl;
#endif
			if (--left->use == 0)
				delete left;
			if (--right->use == 0)
				delete right;
		}
	};
public:
	Expr(int n)
		: p(new Int_node(n)) {}
	Expr(const std::string& op, const Expr& t)
		: p(new Unary_node(op, t.p)) {}
	Expr(const std::string& op, const Expr& tl, const Expr& tr)
		: p(new Binary_node(op, tl.p, tr.p)) {}
	Expr(const Expr& t)
		: p(t.p) { p->use++; }
	Expr& operator=(const Expr&);
	int eval() const { return p->eval(); }
	~Expr() 
	{ 
		if (--p->use == 0)
			delete p; 
	}

private:
	friend std::ostream& operator<<(std::ostream&, const Expr&);
	friend std::ostream& operator<<(std::ostream& o, const Expr::Expr_node& e);

	Expr_node* p;
};

std::ostream& operator<<(std::ostream& o, const Expr::Expr_node& e)
{
	e.print(o);
	return o;
}

std::ostream& operator<<(std::ostream& o, const Expr& e)
{
	e.p->print(o);
	return o;
}

Expr& Expr::operator=(const Expr& t)
{
	t.p->use++;
	if (--p->use == 0)
		delete p;
	p = t.p;
	return *this;
}
} // end of namespace smy
#endif // end of expr.h

           测试的主函数和运行结果如下

#include "stdafx.h"
#include "Expr.h"

using namespace smy;

int _tmain(int argc, _TCHAR* argv[])
{
	Expr t1("*", Expr("-", 3, 4), Expr("+", 5, 6));
	std::cout << t1 << "=" << t1.eval() << std::endl;
	Expr t2("+", t1, t1);
	std::cout << t2 << "=" << t2.eval() << std::endl;
	Expr t3("/", t2, 4);
	std::cout << t3 << "=" << t3.eval() << std::endl;
	Expr t4("%", t3, 3);
	std::cout << t4 << "=" << t4.eval() << std::endl;
	return 0;
}

           运行结构截图如下:


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值