根据模板sizeof()放置新的

Chr*_*art 5 c++ templates signals placement-new c++11

这在c ++ 11中是否合法?使用最新的英特尔编译器进行编译并且似乎可以正常工作,但我只是觉得这是一个侥幸.

 class cbase
        {
        virtual void call();
        };

template<typename T> class functor : public cbase
    {
    public:
        functor(T* obj, void (T::*pfunc)())
            : _obj(obj), _pfunc(pfunc) {}

        virtual void call()
            {
            (_obj)(*_pfunc)();
            }
    private:
        T& _obj;
        void (T::*_pfunc)();            
        //edited: this is no good:
        //const static int size = sizeof(_obj) + sizeof(_pfunc);
    };

class signal
    {
    public:
        template<typename T> void connect(T& obj, void (T::*pfunc)())
            {
            _ptr = new (space) functor<T>(obj, pfunc);
            }
    private:
        cbase* _ptr;
        class _generic_object {};
        typename aligned_storage<sizeof(functor<_generic_object>), 
            alignment_of<functor<_generic_object>>::value>::type space;
        //edited: this is no good:
        //void* space[(c1<_generic_object>::size / sizeof(void*))];

    };
Run Code Online (Sandbox Code Playgroud)

具体来说,我想知道是否void* space[(c1<_generic_object>::size / sizeof(void*))];真的要为c1的成员对象(_obj和_pfunc)提供正确的大小.(事实并非如此).

编辑:所以经过一些更多的研究后,似乎以下将是(更多?)正确:

typename aligned_storage<sizeof(c1<_generic_object>), 
    alignment_of<c1<_generic_object>>::value>::type space;
Run Code Online (Sandbox Code Playgroud)

然而,在检查生成的程序集时,使用带有此空间的placement new似乎会阻止编译器优化掉对"new"的调用(这似乎是在使用常规'_ptr = new c1;'时发生的.

EDIT2:更改了代码,使意图更加清晰.

Jer*_*fin 3

const static int size = sizeof(_obj) + sizeof(_pfunc);将给出成员大小的总和,但这可能与包含这些成员的类的大小不同。编译器可以自由地在成员之间或最后一个成员之后插入填充。因此,将成员的大小加在一起近似于对象可能的最小大小,但不一定给出具有这些成员的对象的大小。

事实上,对象的大小不仅取决于其成员的类型,还取决于它们的顺序。例如:

struct A { 
    int a;
    char b;
};
Run Code Online (Sandbox Code Playgroud)

对比:

struct B { 
    char b;
    int a;
};
Run Code Online (Sandbox Code Playgroud)

在许多情况下,A将小于B。在 中,和A之间通常没有填充,但在 中,通常会有一些填充(例如,对于 4 字节 int,在和之间通常会有 3 个字节的填充)。abBba

因此,您space可能没有足够的...空间来容纳您尝试在 中创建的对象init