C++ C/C++;使用\u堆或使用\u堆栈的模式

C++ C/C++;使用\u堆或使用\u堆栈的模式,c++,c,stack,memory-management,heap,C++,C,Stack,Memory Management,Heap,有没有办法定义一个宏(或类似的东西),允许在堆栈或堆上干净地分配对象 例如。 当前代码: A a; a.someFunc(); 最简单的建议可能是以下内容,但正如您在下面看到的,维护两组代码不是很干净 #ifdef USE_STACK A a; a.someFunc(); #elseif USE_HEAP A* a = new A(); a->someFunc(); #endif 我正在寻找一个设计模式/代理类,根据客户的需要,它可以用任何一种方式编译代码 编辑:该代码

有没有办法定义一个宏(或类似的东西),允许在堆栈或堆上干净地分配对象

例如。 当前代码:

A a;
a.someFunc();
最简单的建议可能是以下内容,但正如您在下面看到的,维护两组代码不是很干净

#ifdef USE_STACK
  A a;
  a.someFunc();
#elseif USE_HEAP
  A* a = new A();
  a->someFunc();
#endif
我正在寻找一个设计模式/代理类,根据客户的需要,它可以用任何一种方式编译代码

编辑:该代码用于为嵌入式设备/(嵌入式)Linux/Windows Mobile构建库。大多数客户只需要基于堆栈的分配。还有一些人要求用一堆换一堆

谢谢,
Charles

通常堆栈的大小是有限的,因此任何大型对象都需要进行堆分配

所有实现RAII guard习惯用法的实例(例如获取和释放互斥)都需要放在堆栈上,以便在您离开上下文(例如通过返回或异常)时将其清除


让您切换的习惯用法通常不是很有用,因为要将对象放在堆栈或堆上,需要根据天气做出仔细的决定。通常情况下,一个或另一个会更好地解决问题,然后切换就没有意义了。

类似的内容可能会有所帮助:

template <typename T>
class HeapWrapper
{
#ifdef USE_STACK
  T obj_;
#else
  T *obj_;
#endif
public:
#ifdef USE_STACK
  HeapWrapper() : obj_() {}
#else
  HeapWrapper() : obj_(new T()) {}
#endif

#ifdef USE_STACK
  const T& obj() const
  { return obj_; }

  T& obj() const
  { return obj_; }
#else
  const T& obj() const
  { return *obj_; }

  T& obj() const
  { return *obj_; }
#endif
};
如果您的编译器已经:

模板
void foo(常量T&…值){
#ifdef使用_堆栈
对象初始化(值…);
#否则
对象->初始化(值…);
#恩迪夫
}

如果您要问这个问题,我认为您应该开始研究自定义分配器。首先,如果您分配了一大块内存,您可以通过更改分配器内部结构将其用作堆栈或堆。您将使用智能指针分配所有对象(以防止内存泄漏),所有内存将从自定义堆中分配给您

这允许您根据客户的需求调整分配实现,同时如果以这种方式进行调整,还可以提供基于堆栈的分配器的性能


您的代码将始终使用“heap”样式的对象创建,因此您只需要一种编码方式,而不需要条件宏。查看块分配器(它创建若干堆固定大小的块,您将下一个大小的第一个空闲块提供给调用者(例如块大小为16字节、32字节、64字节等),分配和释放速度非常快,但内存使用效率很低。

不是最终答案,但我希望它能帮助:

#ifdef USE_STACK
  A a;
#elseif USE_HEAP
  auto_ptr<A> CAUTION_USE_OF_AUTOPTR_a( new A() );
  A& a = CAUTION_USE_OF_AUTOPTR_a.get();
#endif
a.someFunc();
\ifdef使用堆栈
A A;
#否则请使用堆
auto_ptr CAUTION_使用_AUTOPTR_a(新a());
A&A=小心使用自动变速器A.get()的;
#恩迪夫
a、 someFunc();

编辑:经过改进,允许通过
操作符->

扩展Manuel的答案,使其更完整,尝试以下方法:

#include <iostream>

#define USE_STACK

template <class T>
class HeapWrapper {
#ifdef USE_STACK
    T obj_;
#else
    T *obj_;
#endif
public:
#ifdef USE_STACK
    HeapWrapper() : obj_() {}

    template <class A1>
    HeapWrapper(const A1 &a1) : obj_(a1) {}

    template <class A1, class A2>
    HeapWrapper(const A1 &a1, const A2 &a2) : obj_(a1, a2) {}

    // etc

#else
    HeapWrapper() : obj_(new T()) {}
    ~HeapWrapper() { delete obj_; }

    template <class A1>
    HeapWrapper(const A1 &a1) : obj_(new T(a1)) {}

    template <class A1, class A2>
    HeapWrapper(const A1 &a1, const A2 &a2) : obj_(new T(a1, a2)) {}

    // etc
#endif

#ifdef USE_STACK
    operator const T &() const    { return obj_; }
    operator T &()                { return obj_; }
    T *operator->()               { return &obj_; }
    T& operator*()                { return obj_; }
#else
    operator const T &() const    { return *obj_; }
    operator T &()                { return *obj_; }
    T *operator->()               { return obj_; }
    T& operator*()                { return *obj_; }
#endif

    // cast operators makes this work nicely
    HeapWrapper &operator=(const T &rhs) { *obj_ = rhs; return *this;}
};


class A {
public:
    void member(int x) {
        std::cout << x << std::endl;
    }
};


int main() {
    HeapWrapper<int> x1(5);
    HeapWrapper<int> x2;
    HeapWrapper<int> x3 = x1;
    HeapWrapper<int> x4 = 3;

    std::cout << x1 << " " << x2 << " " << x3 << " " << x4 << std::endl;

    // example using a custom class's members..
    HeapWrapper<A> a1;
    a1->member(5);
}
#包括
#定义使用堆栈
模板
类堆振锤{
#ifdef使用_堆栈
T obj_;
#否则
T*obj;
#恩迪夫
公众:
#ifdef使用_堆栈
HeapWrapper():obj_uz(){}
模板
HeapWrapper(常数A1和A1):obj_Ua1{}
模板
HeapWrapper(常数A1和A1,常数A2和A2):obj_(A1,A2){}
//等
#否则
HeapWrapper():对象(新的T()){}
~HeapWrapper(){delete obj;}
模板
HeapWrapper(const A1和A1):对象(新的T(A1)){}
模板
HeapWrapper(常数A1和A1,常数A2和A2):obj(新的T(A1,A2)){}
//等
#恩迪夫
#ifdef使用_堆栈
运算符常量T&()常量{return obj}
运算符T&({return obj}
T*运算符->({return&obj}
T&运算符*(){return obj}
#否则
运算符常量T&()常量{return*obj}
运算符T&({return*obj}
T*运算符->({返回对象j;}
T&运算符*(){return*obj}
#恩迪夫
//cast操作符可以很好地实现这一点
HeapWrapper&operator=(const T&rhs){*obj_=rhs;返回*this;}
};
甲级{
公众:
无效成员(int x){

std::为什么不对实际的构造函数使用可变模板呢?嘿,曼努埃尔,好主意,可以用扩展你的示例来演示如何对上面的对象A使用HeapRapper并调用A.someFunc()?@Manuel:我发布了一个答案,它稍微扩展了你的答案(在一些次要方面有更好的语法)并且正确地覆盖了赋值。另外,在堆模式下,您忘记删除obj_uu。如果没有,您需要使用智能指针来实现相同的技术。智能指针是基于堆栈的,但它包含的内存利用了堆。这看起来非常好,Evan。有没有办法将其封装在类a中?这样会更容易实现更改一个类,而不是更新上面所示的所有客户端代码。要做到这一点,您可以使用工厂模式。基本上,您向a添加一个静态函数,该函数返回HeapRapper或类似的内容。不幸的是,它仍然需要更改创建a对象的所有代码。在更改数量上并没有太大差异还有,为什么有人否决了这个?这是对目前投票率最高的答案的改进…我能想到的唯一真正的烦恼是你不能让操作员超负荷工作。(但操作员->是公平的游戏)。因此,如果你想调用成员,你必须让它看起来像一个指针。我将添加一个这样工作的示例…等一下。我正在考虑你的问题。为什么不将“a”重命名为类似“a_impl”的名称,然后再重命名为“typedef HeapWrapper a”;那么代码的唯一更改就是如何调用成员(将所有a.member()切换为->member())
#ifdef USE_STACK
  A a;
#elseif USE_HEAP
  auto_ptr<A> CAUTION_USE_OF_AUTOPTR_a( new A() );
  A& a = CAUTION_USE_OF_AUTOPTR_a.get();
#endif
a.someFunc();
#include <iostream>

#define USE_STACK

template <class T>
class HeapWrapper {
#ifdef USE_STACK
    T obj_;
#else
    T *obj_;
#endif
public:
#ifdef USE_STACK
    HeapWrapper() : obj_() {}

    template <class A1>
    HeapWrapper(const A1 &a1) : obj_(a1) {}

    template <class A1, class A2>
    HeapWrapper(const A1 &a1, const A2 &a2) : obj_(a1, a2) {}

    // etc

#else
    HeapWrapper() : obj_(new T()) {}
    ~HeapWrapper() { delete obj_; }

    template <class A1>
    HeapWrapper(const A1 &a1) : obj_(new T(a1)) {}

    template <class A1, class A2>
    HeapWrapper(const A1 &a1, const A2 &a2) : obj_(new T(a1, a2)) {}

    // etc
#endif

#ifdef USE_STACK
    operator const T &() const    { return obj_; }
    operator T &()                { return obj_; }
    T *operator->()               { return &obj_; }
    T& operator*()                { return obj_; }
#else
    operator const T &() const    { return *obj_; }
    operator T &()                { return *obj_; }
    T *operator->()               { return obj_; }
    T& operator*()                { return *obj_; }
#endif

    // cast operators makes this work nicely
    HeapWrapper &operator=(const T &rhs) { *obj_ = rhs; return *this;}
};


class A {
public:
    void member(int x) {
        std::cout << x << std::endl;
    }
};


int main() {
    HeapWrapper<int> x1(5);
    HeapWrapper<int> x2;
    HeapWrapper<int> x3 = x1;
    HeapWrapper<int> x4 = 3;

    std::cout << x1 << " " << x2 << " " << x3 << " " << x4 << std::endl;

    // example using a custom class's members..
    HeapWrapper<A> a1;
    a1->member(5);
}