什么才算是在栈上定义的对象?什么是在堆上定义的对象?
-
堆上:即存放的是由new创建的对象和数组,即动态申请的内存都放在堆内存
-
栈上:存放的是用来一些基本类型的变量和对象的引用变量
-
堆就相当于在家自己做饭,吃饭苦逼的还要刷碗,呜呜呜~
-
栈就相当于去饭店吃饭,只管吃,不管其他,生活美滋滋~
【分析】也就是说我们可以将题目理解为:
-
只能在堆上--->只能使用new创建对象
-
只能在栈上--->不能使用new来创建对象
-
而我们知道在不管在哪创建对象我们都需要调用构造函数,既然要有所限制,那么我们首先想到的就是将构造函数声明为私有的,然后具体情况再另行分析,到底行不行,试过就知道了
那具体怎么实现呢?
(一)只能在栈上创建对象
(方案一)我们先把构造函数定义为私有的,然后在类内再定义一个函数来访问构造函数
class B
{
public:
static B getB()
{
return B();
}
private:
B(int b = 0)
:_b(b)
{}
private:
int _b;
};
B::B(const B& b)
{
B* p = new B;//但是不能防止这样的事情发生!
}
int main()
{
B::getB();//在栈上生成对象
//B* pb = new B;//不可访问
system("pause");
return 0;
}
我们看到还是有点问题,那怎么来防止这样的情况发生呢?网上有人给出了这样的答案
(方案二)将operator new 定义为私有的
方法二、将operator new定义为私有的,new的底层就是operator new
class B
{
private:
void* operator new(size_t size);
void operator delete(void*p);
private:
int _b;
};
int main()
{
B b;//在栈上生成对象
//B* pb = new B;//不可访问
system("pause");
return 0;
}
(二)定义一个只能在堆上生成对象的类
(方案一)还是将构造函数定义为私有的
class B
{
public:
static B* GetB()
{
return new B();
}
private:
B(int b = 0)
:_b(b)
{}
private:
int _b;
};
int main()
{
B::GetB();
//B(b);//如此定义,虽然可以防止这样的
B*p = B::GetB();
/*B b(*p);
system("pause");*///但是这样不能防止
return 0;
}
(方案二)我们可以将拷贝构造和赋值运算符重载都定义为私有的,这样就能防止上述情况了
class B
{
public:
static B* GetB()
{
return new B();
}
private:
B(int b = 0)
:_b(b)
{}
B(const B& b);
B& operator=(const B&b);
private:
int _b;
};
int main()
{
B::GetB();
//B(b);//如此定义,虽然可以防止这样
B*p = B::GetB();
/* B b(*p);
system("pause");*///这样可以防止
return 0;
}