堆栈指针模板 我正在阅读“现代C++设计”,并想出一个想法,构建一个像指针一样的类,但是它会在堆栈上分配对象,而不是堆上。它可以用于通常返回指向堆上分配的对象的指针的函数中

堆栈指针模板 我正在阅读“现代C++设计”,并想出一个想法,构建一个像指针一样的类,但是它会在堆栈上分配对象,而不是堆上。它可以用于通常返回指向堆上分配的对象的指针的函数中,c++,templates,metaprogramming,template-meta-programming,boost-mpl,C++,Templates,Metaprogramming,Template Meta Programming,Boost Mpl,在粘贴代码之前,我将询问我的问题: #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 &

在粘贴代码之前,我将询问我的问题:

#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;
}
  • 已经有类似的东西了吗
  • 有机会被利用吗?(当然,如果实施得更准确)
  • 为什么使用
    boost::mpl::max\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;
    }
    
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    模板
    结构最大尺寸
    {
    typedef typename boost::mpl::pop_front::type子向量;
    typedef typename boost::mpl::front::type front\u type;
    静态大小常数值=sizeof(前类型)>最大大小::值?
    sizeof(前\u类型):最大\u大小::值;
    };
    模板
    结构最大尺寸
    {
    静态大小常数值=0;
    };
    类StackPointerImplBase
    {
    公众:
    虚拟空克隆(字符常量*从,字符*到)常量=0;
    };
    模板
    类StackPointerImpl:公共StackPointerImplBase
    {
    公众:
    虚拟空克隆(字符常量*从,字符*到)常量
    {
    新(至)T(*重新解释铸件(自));
    }
    };
    模板
    类堆栈指针
    {
    公众:
    模板
    堆栈指针(T常量和T)
    {
    std::cout()
    {
    返回get_指针();
    }
    私人:
    Base*get_指针()
    {
    返回重新解释(m_buf);
    }
    私人:
    //typedef最大尺寸xxx型;
    //typedef typename boost::mpl::max_元素::type::type最大_类型;
    //charm_buf[sizeof(typename boost::mpl::max_element::type::type)];
    字符m_buf[最大大小::值];
    char m_impl_buf[sizeof(StackPointerImplBase)];
    };
    阶级形态
    {
    公众:
    虚拟~Shape(){}
    虚拟void say()常量{std::cout与您描述的非常相似


    它使用指针语法,因此它可以模拟指针讲话中的
    NULL
    指针。

    您不能在堆栈上分配对象,然后返回指向该对象的任何内容。从函数返回后,堆栈帧消失,指向该内存无效

    在函数中声明局部变量时,它们会在堆栈上分配,然后在函数返回和堆栈框架过时之前销毁

    因此,您可以为堆上的对象分配内存并通过指针引用它们,也可以在堆栈上的函数中使用局部变量

    或者,您的意思是作为处理调用函数返回值的一种方法吗?但是,无论如何,您都需要将数据从堆复制到堆栈,因此,如果您需要/想要在堆栈上复制,为什么不直接使用
    T obj=*foo()


    对我来说,这听起来像是你在试图使编译器已经有效处理过的事情复杂化。

    在我的示例中,我不能做T obj=*foo()因为我不知道返回的类型。我只知道基类。通常,foo会返回指向基类的指针,该基类指向堆上分配的继承类型之一。您不能在堆栈上进行类似的分配。在第二种情况下,您唯一的选择是按值返回。因此,如果函数返回指向堆的指针,则所有已配置的对象。然后呢?我仍然没有遵循您希望在这里完成的操作。您到底希望在堆栈上存储什么?我希望以这种方式避免堆分配。作为一种更便宜的选择。那么,返回指针的函数在何处为它返回的对象分配了内存?我看不出这将如何获得任何好处。当您返回时从使用StackPointer的函数中,您将mbuf中的数据复制到新的StackPointer。这与复制值相同。如果在堆上分配对象,您只需向其传递一个指针,这通常要快得多。因此,您不必只在堆上分配一次对象,而是首先在被调用的函数stac上创建一个字符缓冲区k、 然后将所有数据从复制到调用堆栈帧,很可能复制的字节数超过了对象的大小。正如我所说的,您正在尝试重新设计轮子。如果我正确获取,boost optional允许您返回“NULL”或者一种类型。我的类尝试返回一个对象,该对象可以处理从基类型继承的许多类型。boost::any可能是您想要的。您为什么不想使用堆?在我看来,您的方法的一个主要问题是,所有派生类都必须事先知道。如果我想向
    Shape
    添加一个新的子类,我会这样做ed更改
    ShapeStackPtr
    的所有用法,或创建一种新类型的
    堆栈指针
    。如果指针可以仅与基类一起工作,这可能会很有趣,但我怀疑这是可能的。另一方面,我认为使用自定义分配器或overr可能是处理分配性能问题的最佳方法标识新建/删除。