3

オブジェクトをスタックまたはヒープにきれいに割り当てることができるマクロ(または同様のもの)を定義する方法はありますか?

例えば。現在のコード:

A a;
a.someFunc();

最も簡単な提案は次のとおりですが、以下に示すように、2セットのコードを維持することはあまりクリーンではありません。

#ifdef USE_STACK
  A a;
  a.someFunc();
#elseif USE_HEAP
  A* a = new A();
  a->someFunc();
#endif

お客様のニーズに応じて、どちらの方法でもコードをコンパイルできるデザインパターン/プロキシクラスを探しています。

編集:コードは、組み込みデバイス/(組み込み)Linux /WindowsMo​​bile用のライブラリを構築するために使用されます。ほとんどのお客様は、スタックベースの割り当てのみを望んでいます。他の数人は、スタックをヒープと交換するように依頼しました。

ありがとう、チャールズ

4

5 に答える 5

5

EDIT : ラップされたメンバー関数の呼び出しを許可するように改善されましたoperator->

マヌエルの答えをより完全にするために拡張して、これを試してください:

#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);
}
于 2009-04-09T22:25:40.000 に答える
2

このようなものが役立ちます:

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
};

ただし、これにより、デフォルトのコンストラクターのみを持つオブジェクトに制限されることに注意してください。ラップされたクラスは、ラッパー クラスによる可変個引数テンプレート関数Init(...)によって転送できる関数を提供できます(または、必要なアリティごとに a を追加するだけです)。template <typename T1, template T2, [etc]> Init(const T1 &x1, cons tT2 &x2)

template <typename T1>
void Init(const T1& x1)
{
#ifdef USE_STACK
  obj_.Init(x1);
#else
  obj_->Init(x1);
#endif
}

template <typename T1, typename T2>
void Init(const T1& x1, const T2& x2)
{
#ifdef USE_STACK
  obj_.Init(x1, x2);
#else
  obj_->Init(x1, x2);
#endif
}

コンパイラに可変個引数テンプレートが既にある場合のボーナス ポイント:

template<typename... T>
void foo(const T&... values) {
#ifdef USE_STACK
  obj_.Init(values...);
#else
  obj_->Init(values...);
#endif
}
于 2009-04-09T22:06:40.093 に答える
2

この質問をしている場合は、カスタム アロケーターの調査を開始する必要があると思います。手始めに、メモリの大きなブロックを割り当てる場合、アロケータの内部を変更することで、スタックやヒープのように使用できます。スマート ポインターを使用してすべてのオブジェクトを割り当て (メモリ リークを防ぐため)、すべてのメモリがカスタム ヒープから渡されます。

これにより、顧客のニーズに応じて割り当ての実装を調整でき、そのように調整した場合はスタックベースのアロケーターのパフォーマンスも得られます。

コードは常に「ヒープ」スタイルのオブジェクト作成を使用するため、コーディング方法は 1 つだけで済み、条件付きマクロは必要ありません。ブロック アロケーター (固定サイズ ブロックのヒープをいくつか作成します。次のサイズの最初の空きブロックを呼び出し元に提供します (たとえば、ブロックのサイズは 16 バイト、32 バイト、64 バイトなど))。非常に高速です。割り当てと解放を行いますが、メモリ使用量に関しては非効率的です)。

于 2009-04-09T22:17:06.480 に答える
1

通常、スタックのサイズは制限されているため、大きなオブジェクトはヒープに割り当てる必要があります。

RAIIガードイディオムを実装するすべてのインスタンス(たとえば、ミューテックスを取得して解放するため)は、スタックに配置する必要があります。これにより、コンテキストを離れた場合(たとえば、リターンまたは例外によって)、インスタンスがクリーンアップされます。

オブジェクトをスタックまたはヒープに配置する天候として慎重に決定する必要があるため、切り替えを可能にするイディオムは一般的にあまり有用ではありません。通常、どちらか一方が問題に適しているため、切り替えるのは意味がありません。

于 2009-04-09T22:06:18.627 に答える
0

最終的な回答ではありませんが、お役に立てば幸いです:

#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();
于 2009-04-09T22:17:34.217 に答える