定义一个只能在栈上构造对象的类

只能在堆上定义的对象可以通过声明构造函数是私有的,然后提供两个静态的方法,一个方法用来获取堆上的对象,一个用来释放堆上的对象。C++中定义一个不能被继承的类中第二种方法就是通过这种方式声明了一个不能被继承的类,但是这个类的对象就只能位于堆中了。


那么如何一定一个只能在栈上构造的对象?

这个就涉及到了C++中new这个操作符,它包含两步:

  1. 调用一个全局的operator new函数分配一定的内存空间
  2. 调用对象的构造函数

如果不允许一个类在堆上分配内存,但是允许其在栈上分配内存,对比这两种方式可以发现只需要禁止第一步的操作即可,就是禁止一个对象调用operator new函数。这可能就涉及到了operator new这个库函数了,对于类,这个库函数是可以被重载的,只需要将它重载成私有的即可。这是C++ reference中对operator new的说明。可以查看这个链接中对operator new的说明即可。下面的函数原型就是从上面的文档中拷贝过来的。这里甚至可以不写实现。

#include <iostream>
#include <new>

using namespace std;


class A
{
		public:
				A()
				{
					cout<<"a con"<<endl;
				}

				~A()
				{
					cout<<"a des"<<endl;
				}
		private:
				static void* operator new (std::size_t size) throw (std::bad_alloc);
				static void* operator new (std::size_t size, const std::nothrow_t& nothrow_value) throw();
				static void* operator new (std::size_t size, void* ptr) throw();
		
};
int main()
{
	A a;
	A * ap=new A();
	return 0;
}

可以发现输出提示错误:


如果把main函数中第二行代码去掉,函数是可以正常运行的:

即表示它可以在栈上构造对象。


同时在看上面new的过程中发现了new其实可以使用栈上的内存来构造对象。就是使用placement new这个版本,如果提供给new一个栈上的地址,它会在栈上构造对象。注意使用placement new这个版本时需要显示调用析构函数。

#include <iostream>

using namespace std;

class A
{
		public:
			A(int t=1)
			{
				d=t;
				cout<<d<<"a con"<<endl;
			}
			int d;
			~A()
			{
				cout<<d<<"a des"<<endl;
			}
			

};
int main()
{
	const int Len=sizeof(A);
	char buf[Len];	
	A * a=new(buf) A(2);//调用placement new这个版本
	a->~A();//注意这里需要显示调用析构函数,因为buf中的内存是在栈中的,所以函数跳出后内存会被释放
	return 0;
}

执行输出:




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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值