美文网首页
设计一个只允许在堆或栈上创建的对象

设计一个只允许在堆或栈上创建的对象

作者: cp3_1dbc | 来源:发表于2018-04-10 14:45 被阅读0次

只允许在堆上创建

这很容易做到。非堆对象(non-heap object)在定义它的地方被自动构造,在生存时间结束时自动被释放,所以只要禁止使用隐式的构造函数和析构函数,就可以实现这种限制。

把这些调用变得不合法的一种最直接的方法是把构造函数和析构函数声明为 private。这样做副作用太大。没有理由让这两个函数都是 private。最好让析构函数成为 private,让构造函数成为 public。

  • example1 代码如下:
#include <iostream>

class CreateOnHeap
{
public:
    CreateOnHeap() {}
    
    void destroy() const {
        delete this;    
    }
    
private:
    ~CreateOnHeap() {}
};

int main() {
    //CreateOnHeap c1; //compile error
    CreateOnHeap* c2 = new CreateOnHeap;
    c2->destroy();
    return 0;
}

这样设计有个问题

  1. 这样的类无法作为基类
  2. 者其它类的成员
  • example2 代码如下:
#include <iostream>

class CreateOnHeap
{
public:
    CreateOnHeap() {}
    
    void destroy() const {
        delete this;    
    }
    
private:
    ~CreateOnHeap() {}
};

//作为基类
class CreateOnHeapDerived : public CreateOnHeap
{
public:
    CreateOnHeapDerived() {}
};

//作为其他类成员
class CreateOnHeapOther
{
public:
    CreateOnHeapOther() {}  
private:
    CreateOnHeap _c;
};

int main() {
  return 0;
}

对于第一个问题,可以将基类的析构函数声明为protected(子类可以访问基类的protected成员);对于第二个问题,可以声明为指针类型。

  • example3 代码如下:
class CreateOnHeap2
{
public:
    CreateOnHeap2() {}
    
    void destroy() const {
        delete this;    
    }
    
protected:
    ~CreateOnHeap2() {}
};

class CreateOnHeapDerived2 : public CreateOnHeap2
{
public:
    CreateOnHeapDerived2() {}
};

class CreateOnHeapOther2
{
public:
    CreateOnHeapOther2() {
        _c = new CreateOnHeap2;
    }  
    
    ~CreateOnHeapOther2() {
        _c->destroy();
    }  
private:
    CreateOnHeap2* _c;
};

example2中的创建方法很怪异,用运算符new分配对象却需要用自定义的函数destroy去释放,可以改成下面的实现方式

  • example4 代码如下:
class CreateOnHeap3 { 
protected: 
    CreateOnHeap3() { } 
    ~CreateOnHeap3() { } 
public: 
    static CreateOnHeap3* creatInstance() {
        return new CreateOnHeap3() ;//调用保护的构造函数 
    } 
    void destroy() {
        delete this ;//调用保护的析构函数 
    } 
};

禁止在堆上创建对象

禁止用户直接实例化对象很简单,因为总是调用 new 来建立这种对象,你能够禁止用户调用 new。你不能影响 new 操作符的可用性(这是内嵌于语言的),但是你能够利用 new 操作符总是调用 operator new 函数这点,来达到目的。

class ForbidCreateOnHeap {
private:
    static void *operator new(size_t size);
    static void operator delete(void *ptr);
};
int main() {
    ForbidCreateOnHeap c7; //ok
    static ForbidCreateOnHeap c8; //OK
    ForbidCreateOnHeap* c9 = new ForbidCreateOnHeap; //compile error
}

如果也想禁止堆对象数组,可以把operator new[]和operator delete[]也声明为private。

控制对象的个数

如果只允许产生一个对象,我们很容易可以想到使用单例模式,如果创建多个呢,可以使用一个static变量去记录已经创建的对象的个数。

class CObject
{
public:
    CObject();
    ~CObject();
private:
    static size_t m_nObjCount;
};

CObject::CObject()
{
    if (m_nObjCount > N)
        throw;
    m_nObjCount++;
}

CObject::~CObject()
{
    m_nObjCount--;
}
size_t CObject::m_nObjCount = 0;

相关文章

  • 设计一个只允许在堆或栈上创建的对象

    只允许在堆上创建 这很容易做到。非堆对象(non-heap object)在定义它的地方被自动构造,在生存时间结束...

  • c++基础(创建/实例化对象)

    创建一个对象,根据不同创建方式可以让对象存在于栈或堆内存不同位置,不同类型内存表示对象的声明周期的不同,在栈中对象...

  • OC堆和栈存储内容的区别

    举例:对象存储在堆,而block存储在栈。创建一个对象: 这行代码创建了一个obj对象,指针obj存储在栈,obj...

  • 内存管理 Tagged Pointer

    Tagged Pointer通常创建对象,对象存储在堆中,对象的指针存储在栈中。我们要找到这个对象,就需要先在栈中...

  • 【golang】性能优化

    1.内存管理 在栈中创建对象比在堆中创建对象性能高,少用new来创建对象,多用object{}创建,如果需要创建大...

  • golang 逃逸分析_v1.0.0

    逃逸分析是golang编译器分析一个对象到底应该放到堆内存上,还是栈内存上逃逸是指在某个方法之内创建的对象,除了在...

  • iOS-内存管理 堆栈

    为什么管理内存: 程序在运行的时候,要创建大量的对象,这些对象放在堆和栈上。(基本类型放在栈上,由系统自动管理。)...

  • 【设计模式】创建型设计模式汇总

    创建型设计模式汇总 1. 单例模式 1.1 单例模式的定义 一个类只允许创建一个对象或实例。 1.2 单例模式的作...

  • 内存管理

    1.对象的生成和引用计数 对象是在堆空间上的,alloc 创建内存区域 ,init 初始化内存区域,同时在栈空间上...

  • JVM对象的栈上分配

    前言 并不是所有对象都需要在堆中分配 栈上分配 Java虚拟机中,几乎所有创建的对象都是在堆中进行分配,并且分配在...

网友评论

      本文标题:设计一个只允许在堆或栈上创建的对象

      本文链接:https://www.haomeiwen.com/subject/anzghftx.html