Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 基于模板sizeof()的新放置_C++_Templates_C++11_Signals_Placement New - Fatal编程技术网

C++ 基于模板sizeof()的新放置

C++ 基于模板sizeof()的新放置,c++,templates,c++11,signals,placement-new,C++,Templates,C++11,Signals,Placement New,这在c++11中合法吗?用最新的英特尔编译器编译,看起来可以工作,但我觉得这是一种侥幸 class cbase { virtual void call(); }; template<typename T> class functor : public cbase { public: functor(T* obj, void (T::*pfunc)()) : _obj(obj),

这在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*))];

    };
class-cbase
{
虚空调用();
};
模板类函子:公共cbase
{
公众:
函子(T*obj,void(T::*pfunc)()
:_obj(obj),_pfunc(pfunc){}
虚拟无效调用()
{
(obj)(pfunc)();
}
私人:
T&u obj;
无效(T:*pfunc)();
//编辑:这不好:
//常量静态int size=sizeof(_obj)+sizeof(_pfunc);
};
类信号
{
公众:
模板无效连接(T&obj,无效(T::*pfunc)()
{
_ptr=新(空间)函子(obj,pfunc);
}
私人:
cbase*\u ptr;
类_泛型_对象{};
typename对齐_存储::类型空间;
//编辑:这不好:
//void*空间[(c1::大小/大小(void*))];
};
具体地说,我想知道是否
void*space[(c1::size/sizeof(void*))]
将为c1的成员对象(_obj和_pfunc)提供正确的大小。(事实并非如此)

编辑: 因此,经过更多的研究,以下内容似乎(更多?)是正确的:

typename对齐存储::类型空间;
但是,在检查生成的程序集时,在该空间中使用placement new似乎会阻止编译器优化对“new”的调用(这似乎是在仅使用常规的“_ptr=new c1;”时发生的)


EDIT2:更改代码以使意图更清晰。

const static int size=sizeof(_obj)+sizeof(_pfunc);
将给出成员大小的总和,但这可能与包含这些成员的类的大小不同。编译器可以在成员之间或最后一个成员之后自由插入填充。因此,将成员大小相加近似于该对象可能的最小值,但不一定是g我用这些构件测量一个物体的大小

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

struct A { 
    int a;
    char b;
};
vs:

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


因此,您的
空间
可能没有足够的…空间来容纳您试图在
init
中创建的对象。我认为您很幸运;Jerry的回答指出可能存在填充问题。我认为您拥有的是一个非虚拟类(即,没有vtable),基本上有两个指针(在引擎盖下)

除此之外,算法:
(c1::size/sizeof(void*)
是有缺陷的,因为如果
size
不是
sizeof(void*)
的倍数,它将被截断。您需要类似以下内容:


((c1::size+sizeof(void*)-1)/sizeof(void*))

此代码甚至不涉及填充问题,因为它有一些更直接的问题

<>模板类<代码> C1 < /C> >定义为包含引用类型的成员<代码> t+yObj>代码>应用< <代码> 代码> > Obj> <代码> >代码> >代码>大小,而不是引用成员本身的大小。C++中不可能获得引用的物理大小(至少直接)。同时,任何类型为
c1
的实际对象都会在物理上包含对
T
的引用,通常在这种情况下作为“引擎盖下”的指针来实现

由于这个原因,我完全不清楚为什么
c1::size
的值被用作
c1
(对于任何
T
)类型的实际对象的速度构造所需的内存的度量。这没有任何意义。这些大小根本不相关

纯粹幸运的是,空类
\u generic\u对象的大小可能与引用成员的物理实现的大小计算为相同(或更大)的值。在这种情况下,代码将分配足够的内存量。甚至有人可能会声称
sizeof(\u generic\u object)==sizeof(void*)
相等“通常”在实践中是成立的。但这只是一个完全武断的巧合,没有任何有意义的依据

这甚至看起来像是故意为了纯粹的混淆而在代码中插入的红鲱鱼


在GCC
sizeof
中,空类的p.S.实际计算结果为
1
,而不是任何“对齐”"大小。这意味着上述技术保证使用太小的值初始化
c1::size
。更具体地说,在32位GCC中
c1::size
的值将是
9
,而任何
c1
的实际大小将是
12
字节。

如果不提供在
c1
中为引用成员定义一个初始值设定项?该引用成员中是否有任何特定的重要性?另外,通过
sizeof(_obj)
计算内存大小的背后的想法是什么,它计算为完整对象的大小(即
sizeof T
),然后在该位置构造一个
c1
对象,该对象在物理上只包含对
某些类型的引用(作为指针实现)?我不知道它是否编译,这是一个非常简单的示例,我在这里发布,以转到相关部分。我正在编写一个信号/回调类,希望尽可能消除动态内存分配。嗯,在这一点上,代码似乎没有任何意义。您可能是偶然的吗
struct A { 
    int a;
    char b;
};
struct B { 
    char b;
    int a;
};