0

私は「Modern C++ design」を読んでいて、ポインターのように機能するがヒープではなくスタックにオブジェクトを割り当てるクラスを構築するというアイデアを思いつきました。通常はヒープに割り当てられたオブジェクトへのポインターを返す関数で使用できます。

コードを貼り付ける前に質問します。

  1. すでに似たようなものはありますか?
  2. 利用する機会はありますか?(もちろん、より正確に実装されている場合)
  3. boost::mpl::max_element(コメントアウト)を使用するバージョンが機能しないのはなぜですか?
  4. パラメータがない場合、テンプレート化されたコンストラクタを呼び出す方法は? (つまり:)template <class U> StackPointer() { ... }

コードは次のとおりです。

#include <iostream>

#include <boost/mpl/vector.hpp>
#include <boost/mpl/max_element.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/front.hpp>

template <class V, size_t VS=boost::mpl::size<V>::type::value>
struct max_size
{
    typedef typename boost::mpl::pop_front<V>::type subvector;
    typedef typename boost::mpl::front<V>::type front_type;
    static size_t const value = sizeof(front_type) > max_size<subvector>::value ?
                sizeof(front_type) : max_size<subvector>::value;
};

template <class V>
struct max_size<V, 0>
{
    static size_t const value = 0;
};

class StackPointerImplBase
{
public:
    virtual void clone(char const* from, char* to) const = 0;
};

template <class T>
class StackPointerImpl : public StackPointerImplBase
{
public:
    virtual void clone(char const* from, char *to) const
    {
        new(to) T(*reinterpret_cast<T const*>(from));
    }
};

template <class Base, class DerivedTypes>
class StackPointer
{
public:
    template <class T>
    StackPointer(T const& t)
    {
        std::cout << "Size of m_buf: "  << sizeof(m_buf) << std::endl;
        new(m_impl_buf) StackPointerImpl<T>();
        new(m_buf) T(t);
    }

    StackPointer(StackPointer const& sp)
    {
        //TODO: COPY m_impl_buf
        reinterpret_cast<StackPointerImplBase const*>(sp.m_impl_buf)->clone(sp.m_buf, m_buf);
    }

public:
    ~StackPointer()
    {
        get_pointer()->~Base();
    }

    Base* operator->()
    {
        return get_pointer();
    }

private:
    Base* get_pointer()
    {
        return reinterpret_cast<Base*>(m_buf);
    }

private:
    //typedef max_size<DerivedTypes> xxx_type;
    //typedef typename boost::mpl::max_element<DerivedTypes>::type::type biggest_type;
    //char m_buf[sizeof(typename boost::mpl::max_element<DerivedTypes>::type::type)];
    char m_buf[max_size<DerivedTypes>::value];
    char m_impl_buf[sizeof(StackPointerImplBase)];
};

class Shape
{
public:
    virtual ~Shape() {}

    virtual void say() const { std::cout << "I'm a shape" << std::endl; }
};

class Circle : public Shape
{
public:
    virtual void say() const { std::cout << "I'm a circle" << std::endl; }

private:
    float m_x;
    float m_y;
    float m_r;
};

class Line : public Shape
{
public:
    virtual void say() const { std::cout << "I'm a Line" << std::endl; }

private:
    float m_x1;
    float m_y1;
    float m_x2;
    float m_y2;
};


typedef StackPointer<Shape, boost::mpl::vector<Circle, Line> > ShapeStackPtr;

ShapeStackPtr read_shape()
{
    Line c;
    return ShapeStackPtr(c);
}


int main(int argc, char *argv[])
{

    {
        ShapeStackPtr shape = read_shape();
        shape->say();
    }

    return 0;
}
4

2 に答える 2

0

スタックにオブジェクトを割り当てて、それを指すものを返すことはできません。関数から戻った後、スタック フレームがなくなり、そのメモリを指すことは無効になります。

関数でローカル変数を宣言すると、それらはスタックに割り当てられ、関数が戻る前に破棄され、スタック フレームは廃止されます。

したがって、ヒープ上のオブジェクトにメモリを割り当て、ポインターでそれらを参照できます。または、スタック上の関数にローカル変数を含めます。

それとも、呼び出された関数からの戻り値を処理する方法として意味しますか? ただし、とにかくヒープからスタックにデータのコピーを作成する必要があるため、スタックT obj = *foo()にコピーが必要/必要な場合にのみ使用しないでください。

私には、コンパイラによってすでに効率的に処理されているものを複雑にしようとしているように思えます。

于 2013-03-07T23:35:41.470 に答える
0

オプションのブーストは、あなたが説明したものとかなり似ています。

NULLポインター構文を使用するため、ポインタースピークでポインターとなるものをシミュレートできます。

于 2013-03-07T23:27:55.210 に答える